diff options
Diffstat (limited to 'gnu/usr.bin/ptx')
43 files changed, 11924 insertions, 0 deletions
diff --git a/gnu/usr.bin/ptx/.stamp-h.in b/gnu/usr.bin/ptx/.stamp-h.in new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/gnu/usr.bin/ptx/.stamp-h.in diff --git a/gnu/usr.bin/ptx/COPYING b/gnu/usr.bin/ptx/COPYING new file mode 100644 index 000000000000..a43ea2126fb6 --- /dev/null +++ b/gnu/usr.bin/ptx/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/gnu/usr.bin/ptx/ChangeLog b/gnu/usr.bin/ptx/ChangeLog new file mode 100644 index 000000000000..fffb47f15e79 --- /dev/null +++ b/gnu/usr.bin/ptx/ChangeLog @@ -0,0 +1,546 @@ +Fri Nov 5 23:10:07 1993 Francois Pinard (pinard@icule) + + * Version 0.3 + + * check-out: New name for check_out. + * Makefile.in: Change check_out for check-out everywhere. + Reported by Jim Meyering <meyering@comco.com>. + + * Makefile.in (realclean): Do not remove .stamp-h.in and + config.h.in. One should not need Autoconf installed. + Reported by Nelson Beebe <beebe@math.utah.edu>. + + * ptx.c: Add missing definition of isxdigit. + Reported by Nelson Beebe <beebe@math.utah.edu>. + + * ptx.c: Define S_ISREG if not defined, then use it. + Reported by Karl Berry <karl@cs.umb.edu>. + +Wed Nov 3 15:53:00 1993 Francois Pinard (pinard@icule) + + * mkinstalldirs: New, from elsewhere. + * Makefile.in: Use it. + +Mon Nov 1 00:48:34 1993 Francois Pinard (pinard@lagrande.IRO.UMontreal.CA) + + * Makefile.in (clean): Delete ptx, not the obsolete $(PROGS). + +Sun Oct 31 15:04:57 1993 Francois Pinard (pinard@raptor.IRO.UMontreal.CA) + + * ptx.c (alloc_and_compile_regex): Zero out the whole allocated + pattern, not just a few fields. + + * ptx.c (alloc_and_compile_regex): Clarify error message. + +Thu Oct 28 08:29:29 1993 Francois Pinard (pinard@compy.IRO.UMontreal.CA) + + * ptx.c (print_copyright): Deleted. Rather use a "copyright" + variable, print to standard output instead of standard error. + + * ptx.c: Use error instead of fprintf (stderr, ...). + + * ptx.c: Rename fold_lower_to_upper to ignore_case. + +Wed Oct 27 18:41:52 1993 Francois Pinard (pinard@lagrande.IRO.UMontreal.CA) + + * ptx.c: Add option -M for using another macro name than "xx". + Reported by Thorsten Ohl <ohl@physics.harvard.edu>. + + * examples/ignore/: New files. + * eign: Linked to examples/ignore/eign. + * Makefile.in: Install and uninstall $(datadir)/eign. + * configure.in: Remove testing of a default ignore file. + Reported by Nelson Beebe <beebe@math.utah.edu>. + + * ptx.c (main): Add --help and --version processing. + (print_version): Deleted. + + * ptx.c: Use -traditional instead of --no-gnu-extensions, + --ignore-case instead of --fold-letter-case, --format=<format> + instead of --tex-output and --roff-output. + * argmatch.c: New file. Taken from fileutils/lib. + Reported by Karl Berry <karl@cs.umb.edu>. + +Tue Oct 26 08:39:14 1993 Francois Pinard (pinard@icule) + + * ptx.c (usage): New name for usage_and_exit. Accept an exit + status parameter. If zero, print full help on stdout. If + non-zero, print a one-line helper on stderr. + + * ptx.c: Remove sizeof_occurs and OCCURS_ALIGNMENT complexity. + The memory savings did not justify the portability headaches. + + * ptx.c (copy_unescaped_string): New function. + (main): Use it with options -F, -S and -W. + Reported by Dave Cottingham <dc@haiti.gsfc.nasa.gov>. + + * ptx.c (fix_output_parameters): Force edit of '\f', because some + systems does not consider it to be whitespace. + Reported by Stephane Berube <berube@iro.umontreal.ca>. + + * ptx.c (fix_output_parameters): For roff output, do not disallow + characters with 8th bit set. + Reported by James Clark <jjc@jclark.com>. + + * Makefile.in (dist): Include examples/ in distribution. + +Mon Oct 25 15:46:16 1993 Francois Pinard (pinard@icule) + + * ptx.c: Change --display-width to --width, for consistency with + other GNU programs. + + * examples/ajay/: New files. + Reported by Ajay Shah <ajayshah@cmie.ernet.in>. + Reported by Rakesh Chauhan <rk@cmie.ernet.in>. + + * examples/luke/: New files. + Reported by Luke Kendall <luke@research.canon.oz.au>. + + * examples/latex/: New files. + + * ptx.c (find_occurs_in_text): Assign 0 to refererence_length so + GNU C will not warn anymore against its unitialized use. + Reported by Loic Dachary <L.Dachary@cs.ucl.ac.uk>. + + * lib/: Move routines in main directory first, then destroy. + * Makefile.in: Merge lib/Makefile.in, clean up. + * configure.in: Do not create lib/Makefile.in. + + * acconfig.h: New file. + * .stamp-h.in: Used for timestamping autoheader. + * Makefile.in: Use acconfig.h and .stamp-h.in. Force + autoheader whenever acconfig.h is modified. + +Wed Jun 9 15:01:28 1993 Francois Pinard (pinard@icule) + + * Makefile.in (dist): Replace "echo `pwd`" by a mere "pwd". + Create a gzip file. + +Sat May 22 20:18:31 1993 Francois Pinard (pinard@icule) + + * Makefile.in: Replace $(PROGS) by ptx. + + * diacrit.h: Change `c' to `chr', better protect it. + + * lib/COPYING.LIB: Deleted. + * lib/Makefile.in: Adjust accordingly. + +Sat Feb 6 15:03:13 1993 Francois Pinard (pinard@icule) + + * Makefile.in, lib/Makefile.in: In dist goals, ensure 777 mode for + directories, so older tar's will restore file modes properly. + +Sun Jan 17 15:42:35 1993 Francois Pinard (pinard@icule) + + * Makefile.in, lib/Makefile.in: Put $(CFLAGS) after $(CPPFLAGS), + so the installer can override automatically configured choices. + Reported by Karl Berry <karl@cs.umb.edu>. + +Tue Jan 12 09:21:22 1993 Francois Pinard (pinard at icule) + + * configure.in: Check for setchrclass(). + * diacrit.[hc]: New file, extracted from my own ctype.[hc]. + * ctype.[hc]: Deleted. + * Makefile.in: Distribute diacrit.[hc], but not ctype.[hc]. + * ptx.c: Include "diacrit.h" rather than "ctype.h". + Include <ctype.h> for ANSI C, or else, use our own definitions. + (initialize_regex): Use ctype.h macros for making the folding + table and for making the \w+ fastmap. Previously, was reusing the + regex syntax table or looking at character bit structure. + (main): Execute setchrclass (NULL) if available and ANSI C. + + * Spelling fixes in various files. + Reported by Jim Meyering <meyering@cs.utexas.edu>. + +Thu Jan 7 20:19:25 1993 Francois Pinard (pinard at icule) + + * Makefile.in: Using autoheader, derive config.h.in from + configure.in. Distribute config.h.in. + Use config.status for reconstructing config.h from config.h.in. + Have all $(OBJECTS) depend upon config.h. + Always use -I. calling the C compiler, for config.h to be found. + Remove config.h in distclean-local. + * lib/Makefile.in: Always use -I.. calling the C compiler, for + config.h to be found. Also use $(DEFS). + Have all $(OBJECTS) depend upon ../config.h. + * configure.in: Create config.h from config.h.in. + * ptx.c, ctype.c: Conditionnaly include config.h. + +Fri Jan 1 19:52:49 1993 Francois Pinard (pinard at icule) + + * Makefile.in, lib/Makefile.in: Reinstate $(CPPFLAGS), use it. + Richard wants it there. Remove $(ALLFLAGS) and reequilibrate. + +Sun Dec 27 05:57:55 1992 Francois Pinard (pinard at icule) + + * ptx.c (find_occurs_in_text): Introduce word_start and word_end + variables, and use them instead of the word_regs structure. This + takes care of the fact newer regex.h does not allocate the arrays + any more, and these were used even when regexps were not compiled. + + * Makefile, lib/Makefile.in: Define CHAR_SET_SIZE for SYNTAX_TABLE + to work correctly. + + * configure.in: Replace AC_USG by AC_HAVE_HEADERS(string.h). + Cleanup and reorganize a little. + + * ptx.c: Renamed from gptx.c. Add -G (--no-gnu-extensions) + and clarify some long option names by making them more + explicit. Remove all PTX_COMPATIBILITY conditionals. + Introduce gnu_extensions variable initialized to 1. Let -G + give it the value 0, but still allow and process GNU specific + options and long option names. The Ignore file is now the same + whatever the value of gnu_extensions. + * ptx.texinfo: Renamed from gptx.texinfo, adjusted. + * Makefile.in, configure.in: Adjusted accordingly. Now + installs only one program under the name $(binprefix)ptx. + + * gptx.c (perror_and_exit): Deleted. Use error() directly. + + * gptx.c: Remove unneeded prototypes for system library routines. + + * gptx.c (compare_words, compare_occurs): #define first and second + instead of using an intermediate variable. + + * configure.in: Use AC_CONST. + * gptx.h: Do not define const. + * Define volatile dependent on __GNUC__, not __STDC__, and define + it to __volatile__. + + * gptx.h, version.c: Deleted, integrated into gptx.c. + * Remove src/ and doc/ subdirectories, merging them in main. + * Move lib/bumpalloc.h, lib/ctype.[ch] in main directory. + * Integrate all ChangeLogs in main ChangeLog. + * Integrate all Makefiles in main Makefile and lib/Makefile, + rewriting them all along the way. + +Fri Nov 13 00:10:31 1992 Francois Pinard (pinard at icule) + + * Makefile.in (dist): chmod a+r before making the tar file. + +Tue Oct 6 12:47:00 1992 Francois Pinard (pinard at icule) + + * {,doc/,lib/,src/}Makefile.in: Use exec_prefix. Add `uninstall'. + +Wed Aug 19 16:02:09 1992 Francois Pinard (pinard at icule) + + * ansi2knr.c: New file, from Ghostscript distribution. + * gptx.c: Get rid of many __STDC__ tests. + * version.c: Idem. + +Fri Aug 14 22:53:05 1992 Francois Pinard (pinard at icule) + + * gptx.c: Use HAVE_MCHECK instead of MCHECK_MISSING. + * configure.in: Use AC_HAVE_FUNCS instead of AC_MISSING_FUNCS. + + * configure.in: Autoconfigure for mcheck and strerror. + Reported by Bernd Nordhausen <bernd@iss.nus.sg>. + +Thu Jun 18 09:15:12 1992 Francois Pinard (pinard at icule) + + * configure.in, all Makefile's: Adapt to Autoconf 0.118. + +Sun Feb 2 16:23:47 1992 Francois Pinard (pinard at icule) + + * gptx.c (main): Returns int. + +Tue Dec 10 09:53:21 1991 Francois Pinard (pinard at icule) + + * gptx.c (usage_and_exit): Print --OPTION instead of +OPTION. + +Wed Dec 4 10:31:06 1991 Francois Pinard (pinard at icule) + + * gptx.c (compare_occurs, compare_words): Change parameters to + (void *) to comply with qsort ANSI declaration, and cast the true + type inside the function, each time a parameter is used. + Reported by Byron Rakitzis <byron@archone.tamu.edu>. + +Mon Dec 2 10:41:43 1991 Francois Pinard (pinard at icule) + + * gptx.c: Removed comma at end of enum. + + * version.c: Add a few missing `const's. + + * gptx.c: Add prototypes for close, fstat, open, perror and read + if __STDC__. + + * gptx.c: Remove useless alloca declaration. + +Sat Nov 9 20:03:37 1991 Francois Pinard (pinard at icule) + + * configure.in, all/Makefile.in: Directory reorganization, + including separate src and doc, in plus of lib. Ensure all + Makefile's can be used independently. + +Thu Nov 7 11:20:38 1991 Francois Pinard (pinard at icule) + + * gptx.texinfo: Renamed from gptx.texi. Now `TeX'able. + * Makefile.in: Ensure distributing texinfo.tex. + Reported by Karl Berry <karl@cs.umb.edu>. + + * configure.in: Take care of POSIXish ISC. + Reported by Karl Berry <karl@cs.umb.edu>. + +Tue Nov 5 09:42:58 1991 Francois Pinard (pinard at icule) + + * configure.in, Makefile.in: Do not absolutize $(srcdir), because + this could create problems with automounters. + + * configure.in, Makefile.in: Remove IF_* devices, they were + solving a problem caused only by non timestamping shars, and + gptx is now distributed in tar format. + +Mon Oct 28 14:39:36 1991 Francois Pinard (pinard at icule) + + * configure.in: New file. + * configure: Automatically generated from file configure.in + and David MacKenzie's autoconf. + +Sat Oct 19 20:06:28 1991 Francois Pinard (pinard at icule) + + * configure: Use ANSI header files if present, even with non ANSI + compilers. + Reported by David MacKenzie <djm@eng.umd.edu>. + +Tue Oct 15 08:43:13 1991 Francois Pinard (pinard at icule) + + * Makefile.in: Install gptx and ptx separately. On DEC Ultrix + 4.1, install cannot install more than one file at a time. + Reported by Simon Leinen <simon@liasun1.epfl.ch>. + +Fri Oct 11 15:19:42 1991 Francois Pinard (pinard at icule) + + * Makefile.in: `realclean' did not work, because lib/Makefile was + disappearing at `distclean' time. I tried separate doc and src + directories, but this is not worth the heaviness. Split some + goals instead, using _doc, _lib and _src suffixes. + +Fri Oct 10 18:04:21 1991 Francois Pinard (pinard at icule) + + * Version 0.2 + +Wed Oct 9 16:13:42 1991 Francois Pinard (pinard at icule) + + * configure, Makefile.in: New files. + * Makefile, GNUmakefile, Depends: Deleted. + + * gptx.c: Change -A output from `FILE(NN):' to `FILE:NN:'. + + * gptx.c, gptx.h, version.c: Reinstate __STDC__ tests. + +Tue Jun 25 11:35:32 1991 Francois Pinard (pinard at icule) + + * gptx.c: Something is wrong in -r reference allocation, I suspect + casting does not do what I expect. I relax the constraints so to + make it work for now. To be revisited. + + * gptx.c: Call initialize_regex sooner, to ensure folded_chars is + properly initialized when -f and -i are simultaneously used. + + * gptx.c: Remove -p option and rather compile two separate + programs, one by defining PTX_COMPATIBILITY, to conform a GNU + standard asking to not depend on the program installed name. This + also removes the -p option, so loosing the debatable advantage of + dynamically reverting to ptx compatibility mode. + + * gptx.h: Cleanup. Don't duplicate stdlib.h. + +Wed Dec 5 18:00:23 1990 Francois Pinard (pinard at icule) + + * gptx.c (usage_and_exit): Change -C explanation. + +Sun Oct 28 16:11:36 1990 Francois Pinard (pinard at icule) + + * gptx.h: Remove the PROTO macros and usage. + * gptx.c: Remove all the #ifdef __STDC__ noise. + * version.c: Remove all the #ifdef __STDC__ noise. + +Wed Jul 25 12:20:45 1990 Francois Pinard (pinard at icule) + + * ctype.[ch]: Linked from my library. + +Wed Jul 11 10:53:13 1990 Francois Pinard (pinard at icule) + + * bumpalloc.h: Linked from my library. + +Sun Aug 5 13:17:25 1990 Francois Pinard (pinard at icule) + + * Version 0.1 + + * gptx.c: Implement IGNORE and PIGNORE defines. + + * gptx.c: Implement special character protection for roff and TeX + output, through the edited_flag array. + +Fri Aug 3 12:47:35 1990 Francois Pinard (pinard at icule) + + * gptx.c: Implement new -R option for automatic referencing, with + the possibility of multiple input files in normal mode. Now, + option -r implies ptx compatibility mode default for -S; exclude + reference from context whenever easy to do, and allow coselection + of both -r and -R. + +Wed Aug 1 12:00:07 1990 Francois Pinard (pinard at icule) + + * gptx.[hc]: Define and use OCCURS_ALIGNMENT, to avoid those + `Bus error's on Sparcs. + +Fri Jul 27 12:04:40 1990 Francois Pinard (pinard at icule) + + * gptx.c (initialize_regex): Use only isalpha and "ctype.h" to + initialize Sword syntax, getting rid of any other explicit ISO + 8859-1 references. This will make the MS-DOS port easier, + character set wise. + + * gptx.c (swallow_file_in_memory): Revised along the lines of + io.c from GNU diff 1.14, so it could handle stin and fifos, + and work faster. + + * gptx.c (perror_and_exit): New function, use it where convenient. + +Thu Jul 26 13:28:13 1990 Francois Pinard (pinard at icule) + + * gptx.c (swallow_input_text): Remove white space compression even + if not in ptx compatibility mode. This being out of the way, use + swallow_file_in_memory instead of inputting characters one by one. + +Wed Jul 25 12:20:45 1990 Francois Pinard (pinard at icule) + + * gptx.c (find_occurs_in_text): Include the sentence separator as + part of the right context, except for separator's suffix white + space. Formerly, it was excluded from all contexts. + + * gptx.h: Check STDLIB_PROTO_ALREADY to conditionalize prototype + declarations for standard C library routines; check __GNUC__ + before using `volatile' on function prototypes. + + * gptx.c: (find_occurs_in_text): Maintain the maximum length of + all words read. + (define_all_fields): Optimize scanning longish left contexts by + sometimes doing a backward jump from the keyword instead of always + scanning forward from the left context boundary. + +Sun Jul 22 09:18:21 1990 Francois Pinard (pinard at icule) + + * gptx (alloc_and_compile_regex): Realloc out all extra allocated + space. + +Mon Jul 16 09:07:25 1990 Francois Pinard (pinard at icule) + + * gptx.c: In OCCURS structure, modify left, right and reference + pointers and make them displacements, to save some space. Define + DELTA typedef, use it, make all other necessary changes. + + * gptx.c: Work on portability. Define const and volatile to + nothing if not __STDC__. On BSD, define str[r]chr to be [r]index. + Avoid writings specific to GNU C. + +Sun Jul 15 17:28:39 1990 Francois Pinard (pinard at icule) + + * gptx.c: Add a word_fastmap array and use it if -W has not been + specified, instead of using default regexps. Finish implementing + the Break files. + +Sat Jul 14 10:54:21 1990 Francois Pinard (pinard at icule) + + * gptx.[ch], version.c: Use prototypes in all header + functions. Add some missing const declarations. + +Fri Jul 13 10:16:34 1990 Francois Pinard (pinard at icule) + + * gptx.c: Enforce ptx compatibility mode by disallowing normal + mode extensions. Disallow -p if extensions are used. + + * gptx.c: Finish implementation of Ignore and Only files. + +Wed Jul 11 10:53:13 1990 Francois Pinard (pinard at icule) + + * gptx.c: Revise WORD typedef and use it in OCCURS typedef; + adjust all usages. Add BLOCK and WORD_ARRAY typedefs, revise in + various place to make better usage of these. Use BUMP_ALLOC. + +Tue Jul 10 09:02:26 1990 Francois Pinard (pinard at icule) + + * gptx.c: Add -L option, `latin1_charset' variable and support. + + * gptx.c: Remove old generate_roff and generate_tex variables, + replace with output_format which is of enum type. + +Mon Jul 9 10:40:41 1990 Francois Pinard (pinard at icule) + + * gptx.c (compare_words): Check word_regex.translate and do not + use the translation table if not computed. Also protect against + possible 8-bit problems. + + * gptx.c (alloc_and_compile_regex): New function. + +Sun Jul 8 17:52:14 1990 Francois Pinard (pinard at icule) + + * gptx.c: Make a more systematic use of SKIP_* macros, to get rid + of explicit ' ' references when possible. + + * gptx.c: Replace `head' field by `left' in the OCCURS structure, + delay the `before' computation from find_occurs_in_text to + define_all_fields, and make all necessary adjustments. Also + add a `right' field in the OCCURS structure, use it to get rid of + explicit '\n' references when possible. + + * gptx.c (initialize_regex): New function. Compute the syntax + table for regex. Get rid of previous break_chars_init variable + and break_chars array, use word_regex and word_regex_string + instead. + + * gptx.c: Use re_search to find words and re_match to skip over + them. Add -W option and support. Use re_search to find end of + lines or end of sentences, add -S option and support. + +Sat Jul 7 08:50:40 1990 Francois Pinard (pinard at icule) + + * gptx.c: Change PRINT_SPACES and PRINT_FIELD macros to + print_spaces and print_field routines, respectively. + +Fri Jul 6 09:44:39 1990 Francois Pinard (pinard at icule) + + * gptx.c (generate_output): Split into define_all_fields, + generate_all_output, output_one_roff_line, output_one_tex_line, + and output_one_tty_line. + + * gptx.c: Move the inline code to reallocate the text buffer into + reallocate_text_buffer. Correct a small bug in this area. + + * gptx.c: Modify -F to accept a STRING argument, modify output + routines to handle truncation marks having more than one + character. + +Thu Jul 5 11:08:59 1990 Francois Pinard (pinard at icule) + + * gptx.c: Add -F option and logic. + + * gptx.c: Select ptx compatibility mode if program is + installed under the name `ptx'. Install both gptx and ptx. + +Thu Jun 7 17:21:25 1990 Francois Pinard (pinard at icule) + + * gptx.c: Make each OCCURS a variable size thing, depending on + various options; mark occurs_found table size with an integer + counter instead of an end pointer. + +Sat Apr 14 20:01:09 1990 Francois Pinard (pinard at icule) + + * Version 0.0 + + * gptx.c: Removed limitations on table sizes: it should now go + until an `Out of memory' error. Use xmalloc. Rename some + variables. + + * version.c, gptx.c (usage_and_exit): Add -C option to print + Copyright. + +Mon Mar 12 17:59:42 1990 Francois Pinard (pinard at icule) + + * ChangeLog initialisation. Previous experiments towards gptx + were done at the defunct site ora.odyssee.qc.ca, which was a + Sun-3/160 running SunOS 3.0. The files have been stocked for + a long time to kovic.iro archives, then imported to icule. + + * gptx.c: GCC linted. diff --git a/gnu/usr.bin/ptx/Makefile b/gnu/usr.bin/ptx/Makefile new file mode 100644 index 000000000000..340c09afb7fd --- /dev/null +++ b/gnu/usr.bin/ptx/Makefile @@ -0,0 +1,10 @@ +PROG= ptx +SRCS= argmatch.c diacrit.c error.c getopt.c getopt1.c ptx.c xmalloc.c + +LDADD+= -lgnuregex +DPADD+= ${GNUREGEX} +CFLAGS+= -DHAVE_CONFIG_H -DDEFAULT_IGNORE_FILE=\"/usr/share/dict/eign\" + +NOMAN= + +.include <bsd.prog.mk> diff --git a/gnu/usr.bin/ptx/NEWS b/gnu/usr.bin/ptx/NEWS new file mode 100644 index 000000000000..6f97bf92852e --- /dev/null +++ b/gnu/usr.bin/ptx/NEWS @@ -0,0 +1,53 @@ +GNU permuted indexer NEWS - User visible changes. +Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc. +Francois Pinard <pinard@iro.umontreal.ca>, 1992. + +Version 0.3 - 1993-10-??, by Franc,ois Pinard + +* GNU ptx installs as a single program, -G option dynamically reverts +to the System V compatible behaviour, yet being liberal with options. + +* It should install more easily on more systems, source code is +unprotoized on the fly for older C compilers. + +* A default ignore file is installed along with GNU ptx, ptx uses it. + +* Options -F, -S and -W interpret most \-escapes themselves. + +* Option -M can be use to change "xx" to another macro name. + +* CHRCLASS environment variable is obeyed for systems supporting it. + +* Long option names have been cleaned up a little. + +* Some examples are given in the example/ directory structure. + + +Version 0.2 - 1991-10-10, by Franc,ois Pinard + +* Reference format (with -A) has been modified slightly to better +comply with GNU standards for line reporting. + +* Option -p removed, rather compile two separate programs, one with +GNU extensions, the other being strict on System V compatibility. + + +Version 0.1 - 1990-08-05, by Franc,ois Pinard + +* Add many options: -L for Latin1, -R for automatic referencing, -W +for regular expressions describing words, -S for regular expressions +describing end of lines or sentences. Let -F specify the truncation +strings. + +* Implementing Ignore files and Only files. + +* Option -p dynamically enforces strict System V compatibility. + +* Correct a few bugs and portability problems, have faster input, +faster processing, and use less memory. + + +Version 0.0 - 1990-04-14, by Franc,ois Pinard + +* Initial release. + diff --git a/gnu/usr.bin/ptx/README b/gnu/usr.bin/ptx/README new file mode 100644 index 000000000000..240b7ee8891a --- /dev/null +++ b/gnu/usr.bin/ptx/README @@ -0,0 +1,23 @@ +This is an beta release of GNU ptx, a permuted index generator. GNU +ptx can handle multiple input files at once, produce TeX compatible +output, or a readable KWIC (keywords in their context) without the +need of nroff. This version does not handle huge input files, that +is, those which do not fit in memory all at once. + +The command syntax is not the same as UNIX ptx: all given files are +input files, the results are produced on standard output by default. +GNU ptx manual is provided in Texinfo format. Calling `ptx --help' +prints an option summary. Please note that an overall renaming of all +options is foreseeable: GNU ptx specifications are not frozen yet. + +See the file COPYING for copying conditions. + +See the file THANKS for a list of contributors. + +See the file NEWS for a list of major changes in the current release. + +See the file INSTALL for compilation and installation instructions. + +Mail suggestions and bug reports (including documentation errors) for +these programs to bug-gnu-utils@prep.ai.mit.edu. + diff --git a/gnu/usr.bin/ptx/THANKS b/gnu/usr.bin/ptx/THANKS new file mode 100644 index 000000000000..e6a45cf9c77c --- /dev/null +++ b/gnu/usr.bin/ptx/THANKS @@ -0,0 +1,23 @@ +GNU permuted indexer has originally been written by François Pinard. +Other people contributed to the GNU permuted index by reporting +problems, suggesting various improvements or submitting actual code. +Here is a list of these people. Help me keep it complete and exempt +of errors. + +Ajay Shah ajayshah@cmie.ernet.in +Bernd Nordhausen bernd@iss.nus.sg +Byron Rakitzis byron@archone.tamu.edu +Dave Cottingham dc@haiti.gsfc.nasa.gov +David J. MacKenzie djm@eng.umd.edu +Francois Pinard pinard@iro.umontreal.ca +Janne Himanka shem@syy.oulu.fi +James Clark jjc@jclark.com +Jim Meyering meyering@comco.com +Karl Berry karl@cs.umb.edu +Loic Dachary L.Dachary@cs.ucl.ac.uk +Luke Kendall luke@research.canon.oz.au +Nelson Beebe beebe@math.utah.edu +Rakesh Chauhan rk@cmie.ernet.in +Simon Leinen simon@liasun1.epfl.ch +Stephane Berube berube@iro.umontreal.ca +Thorsten Ohl ohl@physics.harvard.edu diff --git a/gnu/usr.bin/ptx/TODO b/gnu/usr.bin/ptx/TODO new file mode 100644 index 000000000000..6714313c5751 --- /dev/null +++ b/gnu/usr.bin/ptx/TODO @@ -0,0 +1,94 @@ +TODO file for GNU ptx - last revised 05 November 1993. +Copyright (C) 1992, 1993 Free Software Foundation, Inc. +Francois Pinard <pinard@iro.umontreal.ca>, 1992. + +The following are more or less in decreasing order of priority. + +* Use rx instead of regex. + +* Correct the infinite loop using -S '$' or -S '^'. + +* Use mmap for swallowing files (maybe wrong when memory edited). + +* Understand and mimic `-t' option, if I can. + +* Sort keywords intelligently for Latin-1 code. See how to interface +this character set with various output formats. Also, introduce +options to inverse-sort and possibly to reverse-sort. + +* Improve speed for Ignore and Only tables. Consider hashing instead +of sorting. Consider playing with obstacks to digest them. + +* Provide better handling of format effectors obtained from input, and +also attempt white space compression on output which would still +maximize full output width usage. + +* See how TeX mode could be made more useful, and if a texinfo mode +would mean something to someone. + +* Provide multiple language support + +Most of the boosting work should go along the line of fast recognition +of multiple and complex boundaries, which define various `languages'. +Each such language has its own rules for words, sentences, paragraphs, +and reporting requests. This is less difficult than I first thought: + + . Recognize language modifiers with each option. At least -b, -i, -o, +-W, -S, and also new language switcher options, will have such +modifiers. Modifiers on language switchers will allow or disallow +language transitions. + + . Complete the transformation of underlying variables into arrays in +the code. + + . Implement a heap of positions in the input file. There is one entry +in the heap for each compiled regexp; it is initialized by a re_search +after each regexp compile. Regexps reschedule themselves in the heap +when their position passes while scanning input. In this way, looking +simultaneously for a lot of regexps should not be too inefficient, +once the scanning starts. If this works ok, maybe consider accepting +regexps in Only and Ignore tables. + + . Merge with language processing boundary processing options, really +integrating -S processing as a special case. Maybe, implement several +level of boundaries. See how to implement a stack of languages, for +handling quotations. See if more sophisticated references could be +handled as another special case of a language. + +* Tackle other aspects, in a more long term view + + . Add options for statistics, frequency lists, referencing, and all +other prescreening tools and subsidiary tasks of concordance +production. + + . Develop an interactive mode. Even better, construct a GNU emacs +interface. I'm looking at Gene Myers <gene@cs.arizona.edu> suffix +arrays as a possible implementation along those ideas. + + . Implement hooks so word classification and tagging should be merged +in. See how to effectively hook in lemmatisation or other +morphological features. It is far from being clear by now how to +interface this correctly, so some experimentation is mandatory. + + . Profile and speed up the whole thing. + + . Make it work on small address space machines. Consider three levels +of hugeness for files, and three corresponding algorithms to make +optimal use of memory. The first case is when all the input files and +all the word references fit in memory: this is the case currently +implemented. The second case is when the files cannot fit all together +in memory, but the word references do. The third case is when even +the word references cannot fit in memory. + + . There also are subsidiary developments for in-core incremental sort +routines as well as for external sort packages. The need for more +flexible sort packages comes partly from the fact that linguists use +kinds of keys which compare in unusual and more sophisticated ways. +GNU `sort' and `ptx' could evolve together. + + +Local Variables: +mode: outline +outline-regexp: " *[-+*.] \\|" +eval: (hide-body) +End: diff --git a/gnu/usr.bin/ptx/alloca.c b/gnu/usr.bin/ptx/alloca.c new file mode 100644 index 000000000000..bd4932aa4453 --- /dev/null +++ b/gnu/usr.bin/ptx/alloca.c @@ -0,0 +1,484 @@ +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + J.Otto Tennant <jot@cray.com> contributed the Cray support. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +#include <config.h> +#else +#include "config.h" +#endif +#endif + +/* If compiling with GCC 2, this file's not needed. */ +#if !defined (__GNUC__) || __GNUC__ < 2 + +/* If someone has defined alloca as a macro, + there must be some other way alloca is supposed to work. */ +#ifndef alloca + +#ifdef emacs +#ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +#ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +#endif /* STACK_DIRECTION undefined */ +#endif /* static */ +#endif /* emacs */ + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) +long i00afunc (); +#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) +#else +#define ADDRESS_FUNCTION(arg) &(arg) +#endif + +#if __STDC__ +typedef void *pointer; +#else +typedef char *pointer; +#endif + +#define NULL 0 + +/* Different portions of Emacs need to call different versions of + malloc. The Emacs executable needs alloca to call xmalloc, because + ordinary malloc isn't protected from input signals. On the other + hand, the utilities in lib-src need alloca to call malloc; some of + them are very simple, and don't have an xmalloc routine. + + Non-Emacs programs expect this to call use xmalloc. + + Callers below should use malloc. */ + +#ifndef emacs +#define malloc xmalloc +#endif +extern pointer malloc (); + +/* Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ + +#ifndef STACK_DIRECTION +#define STACK_DIRECTION 0 /* Direction unknown. */ +#endif + +#if STACK_DIRECTION != 0 + +#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ + +#else /* STACK_DIRECTION == 0; need run-time code. */ + +static int stack_dir; /* 1 or -1 once known. */ +#define STACK_DIR stack_dir + +static void +find_stack_direction () +{ + static char *addr = NULL; /* Address of first `dummy', once known. */ + auto char dummy; /* To get stack address. */ + + if (addr == NULL) + { /* Initial entry. */ + addr = ADDRESS_FUNCTION (dummy); + + find_stack_direction (); /* Recurse once. */ + } + else + { + /* Second entry. */ + if (ADDRESS_FUNCTION (dummy) > addr) + stack_dir = 1; /* Stack grew upward. */ + else + stack_dir = -1; /* Stack grew downward. */ + } +} + +#endif /* STACK_DIRECTION == 0 */ + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +pointer +alloca (size) + unsigned size; +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* Unknown growth direction. */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = malloc (sizeof (header) + size); + /* Address of header. */ + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) + +#ifdef DEBUG_I00AFUNC +#include <stdio.h> +#endif + +#ifndef CRAY_STACK +#define CRAY_STACK +#ifndef CRAY2 +/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ +struct stack_control_header + { + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ + }; + +/* The stack segment linkage control information occurs at + the high-address end of a stack segment. (The stack + grows from low addresses to high addresses.) The initial + part of the stack segment linkage control information is + 0200 (octal) words. This provides for register storage + for the routine which overflows the stack. */ + +struct stack_segment_linkage + { + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ + long:32; + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ + long:32; + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ + long ssa0; + long ssa1; + long ssa2; + long ssa3; + long ssa4; + long ssa5; + long ssa6; + long ssa7; + long sss0; + long sss1; + long sss2; + long sss3; + long sss4; + long sss5; + long sss6; + long sss7; + }; + +#else /* CRAY2 */ +/* The following structure defines the vector of words + returned by the STKSTAT library routine. */ +struct stk_stat + { + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ + }; + +/* The following structure describes the data structure which trails + any stack segment. I think that the description in 'asdef' is + out of date. I only describe the parts that I am sure about. */ + +struct stk_trailer + { + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ + long unknown2; + long unknown3; + long link; /* Address of trailer block of previous + segment. */ + long unknown5; + long unknown6; + long unknown7; + long unknown8; + long unknown9; + long unknown10; + long unknown11; + long unknown12; + long unknown13; + long unknown14; + }; + +#endif /* CRAY2 */ +#endif /* not CRAY_STACK */ + +#ifdef CRAY2 +/* Determine a "stack measure" for an arbitrary ADDRESS. + I doubt that "lint" will like this much. */ + +static long +i00afunc (long *address) +{ + struct stk_stat status; + struct stk_trailer *trailer; + long *block, size; + long result = 0; + + /* We want to iterate through all of the segments. The first + step is to get the stack status structure. We could do this + more quickly and more directly, perhaps, by referencing the + $LM00 common block, but I know that this works. */ + + STKSTAT (&status); + + /* Set up the iteration. */ + + trailer = (struct stk_trailer *) (status.current_address + + status.current_size + - 15); + + /* There must be at least one stack segment. Therefore it is + a fatal error if "trailer" is null. */ + + if (trailer == 0) + abort (); + + /* Discard segments that do not contain our argument address. */ + + while (trailer != 0) + { + block = (long *) trailer->this_address; + size = trailer->this_size; + if (block == 0 || size == 0) + abort (); + trailer = (struct stk_trailer *) trailer->link; + if ((block <= address) && (address < (block + size))) + break; + } + + /* Set the result to the offset in this segment and add the sizes + of all predecessor segments. */ + + result = address - block; + + if (trailer == 0) + { + return result; + } + + do + { + if (trailer->this_size <= 0) + abort (); + result += trailer->this_size; + trailer = (struct stk_trailer *) trailer->link; + } + while (trailer != 0); + + /* We are done. Note that if you present a bogus address (one + not in any segment), you will get a different number back, formed + from subtracting the address of the first block. This is probably + not what you want. */ + + return (result); +} + +#else /* not CRAY2 */ +/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. + Determine the number of the cell within the stack, + given the address of the cell. The purpose of this + routine is to linearize, in some sense, stack addresses + for alloca. */ + +static long +i00afunc (long address) +{ + long stkl = 0; + + long size, pseg, this_segment, stack; + long result = 0; + + struct stack_segment_linkage *ssptr; + + /* Register B67 contains the address of the end of the + current stack segment. If you (as a subprogram) store + your registers on the stack and find that you are past + the contents of B67, you have overflowed the segment. + + B67 also points to the stack segment linkage control + area, which is what we are really interested in. */ + + stkl = CRAY_STACKSEG_END (); + ssptr = (struct stack_segment_linkage *) stkl; + + /* If one subtracts 'size' from the end of the segment, + one has the address of the first word of the segment. + + If this is not the first segment, 'pseg' will be + nonzero. */ + + pseg = ssptr->sspseg; + size = ssptr->sssize; + + this_segment = stkl - size; + + /* It is possible that calling this routine itself caused + a stack overflow. Discard stack segments which do not + contain the target address. */ + + while (!(this_segment <= address && address <= stkl)) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); +#endif + if (pseg == 0) + break; + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + this_segment = stkl - size; + } + + result = address - this_segment; + + /* If you subtract pseg from the current end of the stack, + you get the address of the previous stack segment's end. + This seems a little convoluted to me, but I'll bet you save + a cycle somewhere. */ + + while (pseg != 0) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o\n", pseg, size); +#endif + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + result += size; + } + return (result); +} + +#endif /* not CRAY2 */ +#endif /* CRAY */ + +#endif /* no alloca */ +#endif /* not GCC version 2 */ diff --git a/gnu/usr.bin/ptx/argmatch.c b/gnu/usr.bin/ptx/argmatch.c new file mode 100644 index 000000000000..17e088b7e806 --- /dev/null +++ b/gnu/usr.bin/ptx/argmatch.c @@ -0,0 +1,94 @@ +/* argmatch.c -- find a match for a string in an array + Copyright (C) 1990 Free Software Foundation, Inc. + + 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, 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. */ + +/* Written by David MacKenzie <djm@ai.mit.edu> */ + +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#include <stdio.h> +#ifdef STDC_HEADERS +#include <string.h> +#endif + +extern char *program_name; + +/* If ARG is an unambiguous match for an element of the + null-terminated array OPTLIST, return the index in OPTLIST + of the matched element, else -1 if it does not match any element + or -2 if it is ambiguous (is a prefix of more than one element). */ + +int +argmatch (arg, optlist) + char *arg; + char **optlist; +{ + int i; /* Temporary index in OPTLIST. */ + int arglen; /* Length of ARG. */ + int matchind = -1; /* Index of first nonexact match. */ + int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */ + + arglen = strlen (arg); + + /* Test all elements for either exact match or abbreviated matches. */ + for (i = 0; optlist[i]; i++) + { + if (!strncmp (optlist[i], arg, arglen)) + { + if (strlen (optlist[i]) == arglen) + /* Exact match found. */ + return i; + else if (matchind == -1) + /* First nonexact match found. */ + matchind = i; + else + /* Second nonexact match found. */ + ambiguous = 1; + } + } + if (ambiguous) + return -2; + else + return matchind; +} + +/* Error reporting for argmatch. + KIND is a description of the type of entity that was being matched. + VALUE is the invalid value that was given. + PROBLEM is the return value from argmatch. */ + +void +invalid_arg (kind, value, problem) + char *kind; + char *value; + int problem; +{ + fprintf (stderr, "%s: ", program_name); + if (problem == -1) + fprintf (stderr, "invalid"); + else /* Assume -2. */ + fprintf (stderr, "ambiguous"); + fprintf (stderr, " %s `%s'\n", kind, value); +} diff --git a/gnu/usr.bin/ptx/bumpalloc.h b/gnu/usr.bin/ptx/bumpalloc.h new file mode 100644 index 000000000000..bbf901fc1d47 --- /dev/null +++ b/gnu/usr.bin/ptx/bumpalloc.h @@ -0,0 +1,58 @@ +/* BUMP_ALLOC macro - increase table allocation by one element. + Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc. + Francois Pinard <pinard@iro.umontreal.ca>, 1990. + + 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, 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. */ + +/*-------------------------------------------------------------------------. +| Bump the allocation of the array pointed to by TABLE whenever required. | +| The table already has already COUNT elements in it, this macro ensure it | +| has enough space to accommodate at least one more element. Space is | +| allocated (2 ^ EXPONENT) elements at a time. Each element of the array | +| is of type TYPE. | +`-------------------------------------------------------------------------*/ + +/* Routines `xmalloc' and `xrealloc' are called to do the actual memory + management. This implies that the program will abort with an `Virtual + Memory exhausted!' error if any problem arise. + + To work correctly, at least EXPONENT and TYPE should always be the + same for all uses of this macro for any given TABLE. A secure way to + achieve this is to never use this macro directly, but use it to define + other macros, which would then be TABLE-specific. + + The first time through, COUNT is usually zero. Note that COUNT is not + updated by this macro, but it should be update elsewhere, later. This + is convenient, because it allows TABLE[COUNT] to refer to the new + element at the end. Once its construction is completed, COUNT++ will + record it in the table. Calling this macro several times in a row + without updating COUNT is a bad thing to do. */ + +#define BUMP_ALLOC(Table, Count, Exponent, Type) \ + BUMP_ALLOC_WITH_SIZE ((Table), (Count), (Exponent), Type, sizeof (Type)) + +/* In cases `sizeof TYPE' would not always yield the correct value for + the size of each element entry, this macro accepts a supplementary + SIZE argument. The EXPONENT, TYPE and SIZE parameters should still + have the same value for all macro calls related to a specific TABLE. */ + +#define BUMP_ALLOC_WITH_SIZE(Table, Count, Exponent, Type, Size) \ + if (((Count) & (~(~0 << (Exponent)))) == 0) \ + if ((Count) == 0) \ + (Table) = (Type *) xmalloc ((1 << (Exponent)) * (Size)); \ + else \ + (Table) = (Type *) \ + xrealloc ((Table), ((Count) + (1 << (Exponent))) * (Size)); \ + else diff --git a/gnu/usr.bin/ptx/check-out b/gnu/usr.bin/ptx/check-out new file mode 100644 index 000000000000..4d13c48bd337 --- /dev/null +++ b/gnu/usr.bin/ptx/check-out @@ -0,0 +1,65 @@ +:30: /ranslate to certain respons ibilities for you if you distr/ +:183: c/ These actions are proh ibited by law if you do not ac +:278: AS BEEN ADVISED OF THE POSS IBILITY OF SUCH DAMAGES. /Y H +:232: /his License may add an expl icit geographical distribution/ +:267: /COST OF ALL NECESSARY SERV ICING, REPAIR OR CORRECTION. +:216: /ht claims or to contest val idity of any such claims; this/ +:45: e/ If the software is mod ified by someone else and pass +:57: pying, distribution and mod ification follow. /for co +:60: /PYING, DISTRIBUTION AND MOD IFICATION 0. This License a/ +:68: /either verbatim or with mod ifications and/or translated i/ +:70: limitation in the term "mod ification".) /ithout +:72: /pying, distribution and mod ification are not covered by t/ +:92: /opy and distribute such mod ifications or work under the t/ +:95: /a) You must cause the mod ified files to carry prominent/ +:103: ommands in/ c) If the mod ified program normally reads c +:114: quirements apply to the mod ified work as a whole. /se re +:115: are not derived/ If ident ifiable sections of that work +:156: of the work for making mod ifications to it. /ed form +:243: Lice/ If the Program spec ifies a version number of this +:46: /hat they have is not the or iginal, so that any problems i/ +:47: /will not reflect on the or iginal authors' reputations. +:191: /eives a license from the or iginal licensor to copy, distr/ +:231: /yrighted interfaces, the or iginal copyright holder who pl/ +:265: /ED WARRANTIES OF MERCHANTAB ILITY AND FITNESS FOR A PARTIC/ +:274: /NG OUT OF THE USE OR INAB ILITY TO USE THE PROGRAM (INCL/ +:303: /warranty of MERCHANTAB ILITY or FITNESS FOR A PARTICU/ +:69: /ation is included without l imitation in the term "modific/ +:198: /for any other reason (not l imited to patent issues), cond/ +:232: /geographical distribution l imitation excluding those coun/ +:235: /License incorporates the l imitation as if written in the/ +:239: Such new versions will be s imilar in spirit to the presen/ +:264: /PLIED, INCLUDING, BUT NOT L IMITED TO, THE IMPLIED WARRANT/ +:274: /ROGRAM (INCLUDING BUT NOT L IMITED TO LOSS OF DATA OR DATA/ +:67: /hat is to say, a work conta ining the Program or a portion/ +:158: /ny associated interface def inition files, plus the script/ +:34: /fee, you must give the rec ipients all the rights that yo/ +:46: /passed on, we want its rec ipients to know that what they/ +:84: /nty; and give any other rec ipients of the Program a copy/ +:190: /ed on the Program), the rec ipient automatically receives/ +:193: /her restrictions on the rec ipients' exercise of the right/ +:239: /sions will be similar in sp irit to the present version, b/ +:254: o goals of prese/ Our dec ision will be guided by the tw +:273: /OR CONSEQUENTIAL DAMAGES AR ISING OUT OF THE USE OR INAB/ +:315: /teractive mode: Gnomov ision version 69, Copyright (C/ +:316: /y name of author Gnomov ision comes with ABSOLUTELY NO/ +:330: /st in the program `Gnomov ision' (which makes passes at/ +:30: /late to certain responsibil ities for you if you distribut/ +:56: The precise terms and cond itions for copying, distributi/ +:60: /C LICENSE TERMS AND COND ITIONS FOR COPYING, DISTRIBUTI/ +:93: /also meet all of these cond itions: a) You must cause/ +:109: /rogram under these cond itions, and telling the user h/ +:129: ther work not bas/ In add ition, mere aggregation of ano +:186: /and all its terms and cond itions for copying, distributi/ +:192: ect to these terms and cond itions. /am subj +:199: /ted to patent issues), cond itions are imposed on you (whe/ +:200: /e) that contradict the cond itions of this License, they d/ +:201: ot excuse you from the cond itions of this License. /do n +:244: /ollowing the terms and cond itions either of that version/ +:251: /ams whose distribution cond itions are different, write to/ +:262: /WHEN OTHERWISE STATED IN WR ITING THE COPYRIGHT HOLDERS AN/ +:270: /ABLE LAW OR AGREED TO IN WR ITING WILL ANY COPYRIGHT HOLDE/ +:280: ly/ END OF TERMS AND COND ITIONS Appendix: How to App +:318: /e it under certain cond itions; type `show c' for deta/ +:52: /of a free program will ind ividually obtain patent licens/ +:72: stribution and mod/ Act ivities other than copying, di diff --git a/gnu/usr.bin/ptx/config.h b/gnu/usr.bin/ptx/config.h new file mode 100644 index 000000000000..93e7ed1fc688 --- /dev/null +++ b/gnu/usr.bin/ptx/config.h @@ -0,0 +1,57 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define if type char is unsigned and you are not using gcc. */ +/* #undef __CHAR_UNSIGNED__ */ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca.h and it should be used (not Ultrix). */ +/* #undef HAVE_ALLOCA_H */ + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #undef HAVE_DOPRNT */ + +/* Define if you have the vprintf function. */ +#define HAVE_VPRINTF 1 + +/* Define if you need to in order for stat and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* In regex, request the capability of modifying the letter syntax. */ +#define SYNTAX_TABLE 1 + +/* In regex, use 8 bits per character. */ +#define CHAR_SET_SIZE 256 + +/* Define if you have mcheck. */ +/* #undef HAVE_MCHECK */ + +/* Define if you have setchrclass. */ +/* #undef HAVE_SETCHRCLASS */ + +/* Define if you have strerror. */ +#define HAVE_STRERROR 1 + +/* Define if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 diff --git a/gnu/usr.bin/ptx/diacrit.c b/gnu/usr.bin/ptx/diacrit.c new file mode 100644 index 000000000000..29e319bbdc49 --- /dev/null +++ b/gnu/usr.bin/ptx/diacrit.c @@ -0,0 +1,148 @@ +/* Diacritics processing for a few character codes. + Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Francois Pinard <pinard@iro.umontreal.ca>, 1988. + + All this file is a temporary hack, waiting for locales in GNU. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "diacrit.h" + +/* ISO 8859-1 Latin-1 code is used as the underlying character set. If + MSDOS is defined, IBM-PC's character set code is used instead. */ + +/*--------------------------------------------------------------------. +| For each alphabetic character, returns what it would be without its | +| possible diacritic symbol. | +`--------------------------------------------------------------------*/ + +const char diacrit_base[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 0, 0, 0, 0, 0, + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', 0, 0, 0, 0, 0, + +#ifdef MSDOS + + 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', + 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', + 'E', 'e', 'E', 'o', 'o', 'o', 'u', 'u', + 'y', 'O', 'U', 0, 0, 0, 0, 0, + 'a', 'i', 'o', 'u', 'n', 'N', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +#else /* not MSDOS */ + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', + 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', + 0, 'N', 'O', 'O', 'O', 'O', 'O', 0, + 'O', 'U', 'U', 'U', 'U', 'Y', 0, 0, + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', + 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', + 0, 'n', 'o', 'o', 'o', 'o', 'o', 0, + 'o', 'u', 'u', 'u', 'u', 'y', 0, 'y', + +#endif /* not MSDOS */ +}; + +/*------------------------------------------------------------------------. +| For each alphabetic character, returns a code of what its diacritic is, | +| according to the following codes: 1 (eE) over aA for latin diphtongs; 2 | +| (') acute accent; 3 (`) grave accent; 4 (^) circumflex accent; 5 (") | +| umlaut or diaraesis; 6 (~) tilda; 7 (,) cedilla; 8 (o) covering degree | +| symbol; 9 (|) slashed character. | +`------------------------------------------------------------------------*/ + +const char diacrit_diac[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, + +#ifdef MSDOS + + 7, 5, 2, 4, 5, 3, 8, 7, + 4, 5, 3, 5, 4, 3, 5, 8, + 2, 1, 1, 4, 5, 3, 4, 3, + 5, 5, 5, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + +#else /* not MSDOS */ + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 2, 4, 6, 5, 8, 1, 7, + 3, 2, 4, 5, 3, 2, 4, 5, + 0, 6, 3, 2, 4, 6, 5, 0, + 9, 3, 2, 4, 5, 2, 0, 0, + 3, 2, 4, 6, 5, 8, 1, 7, + 3, 2, 4, 5, 3, 2, 4, 5, + 0, 6, 3, 2, 4, 6, 5, 0, + 9, 3, 2, 4, 5, 2, 0, 0, + +#endif /* not MSDOS */ +}; diff --git a/gnu/usr.bin/ptx/diacrit.h b/gnu/usr.bin/ptx/diacrit.h new file mode 100644 index 000000000000..c880a45ca8c8 --- /dev/null +++ b/gnu/usr.bin/ptx/diacrit.h @@ -0,0 +1,16 @@ +/* Diacritics processing for a few character codes. + Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Francois Pinard <pinard@iro.umontreal.ca>, 1988. + + All this file is a temporary hack, waiting for locales in GNU. +*/ + +extern const char diacrit_base[]; /* characters without diacritics */ +extern const char diacrit_diac[]; /* diacritic code for each character */ + +/* Returns CHR without its diacritic. CHR is known to be alphabetic. */ +#define tobase(chr) (diacrit_base[(unsigned char) (chr)]) + +/* Returns a diacritic code for CHR. CHR is known to be alphabetic. */ +#define todiac(chr) (diacrit_diac[(unsigned char) (chr)]) + diff --git a/gnu/usr.bin/ptx/error.c b/gnu/usr.bin/ptx/error.c new file mode 100644 index 000000000000..41d66fb4f4f7 --- /dev/null +++ b/gnu/usr.bin/ptx/error.c @@ -0,0 +1,117 @@ +/* error.c -- error handler for noninteractive utilities + Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + 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, 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. */ + +/* Written by David MacKenzie. */ + +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#include <stdio.h> + +#ifdef HAVE_VPRINTF + +#if __STDC__ +#include <stdarg.h> +#define VA_START(args, lastarg) va_start(args, lastarg) +#else /* !__STDC__ */ +#include <varargs.h> +#define VA_START(args, lastarg) va_start(args) +#endif /* !__STDC__ */ + +#else /* !HAVE_VPRINTF */ + +#ifdef HAVE_DOPRNT +#define va_alist args +#define va_dcl int args; +#else /* !HAVE_DOPRNT */ +#define va_alist a1, a2, a3, a4, a5, a6, a7, a8 +#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; +#endif /* !HAVE_DOPRNT */ + +#endif /* !HAVE_VPRINTF */ + +#ifdef STDC_HEADERS +#include <stdlib.h> +#include <string.h> +#else /* !STDC_HEADERS */ +void exit (); +#endif /* !STDC_HEADERS */ + +extern char *program_name; + +#ifndef HAVE_STRERROR +static char * +private_strerror (errnum) + int errnum; +{ + extern char *sys_errlist[]; + extern int sys_nerr; + + if (errnum > 0 && errnum <= sys_nerr) + return sys_errlist[errnum]; + return "Unknown system error"; +} +#define strerror private_strerror +#endif /* !HAVE_STRERROR */ + +/* Print the program name and error message MESSAGE, which is a printf-style + format string with optional args. + If ERRNUM is nonzero, print its corresponding system error message. + Exit with status STATUS if it is nonzero. */ +/* VARARGS */ +void +#if defined (HAVE_VPRINTF) && __STDC__ +error (int status, int errnum, char *message, ...) +#else /* !HAVE_VPRINTF or !__STDC__ */ +error (status, errnum, message, va_alist) + int status; + int errnum; + char *message; + va_dcl +#endif /* !HAVE_VPRINTF or !__STDC__ */ +{ +#ifdef HAVE_VPRINTF + va_list args; +#endif /* HAVE_VPRINTF */ + + fprintf (stderr, "%s: ", program_name); +#ifdef HAVE_VPRINTF + VA_START (args, message); + vfprintf (stderr, message, args); + va_end (args); +#else /* !HAVE_VPRINTF */ +#ifdef HAVE_DOPRNT + _doprnt (message, &args, stderr); +#else /* !HAVE_DOPRNT */ + fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); +#endif /* !HAVE_DOPRNT */ +#endif /* !HAVE_VPRINTF */ + if (errnum) + fprintf (stderr, ": %s", strerror (errnum)); + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} diff --git a/gnu/usr.bin/ptx/examples/README b/gnu/usr.bin/ptx/examples/README new file mode 100644 index 000000000000..038034f52618 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/README @@ -0,0 +1,21 @@ +Various examples of GNU ptx usages. +Francois Pinard <pinard@iro.umontreal.ca>, 1993. + +This directory contains a few examples contributed by GNU ptx users. +Feel free to look at them for tricks or ideas. When an example +requires many files, a subdirectory is used to hold them together. +I have not necessarily tested these examples recently, if at all. + +If you have examples you would like to share, please submit them to +me. You may also submit corrections to the examples given in this +directory, however, please write to the authors first, since they most +probably will like to have their say about their own contribution. + +* include.pl: A Perl script studying system include files. + +* luke/: A shell script permuting indices for man pages. It contains +two examples of an .xx definition for *roff, one simple, one complex. + +* latex/: A simple example of \xx definition for latex. + +* ajay/: A more complex application of latex with ptx. diff --git a/gnu/usr.bin/ptx/examples/ajay/Makefile b/gnu/usr.bin/ptx/examples/ajay/Makefile new file mode 100644 index 000000000000..bff099c5f23c --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/Makefile @@ -0,0 +1,28 @@ +JUNKFILES = tip-index.ps tip-index.dvi tip-index.tex tip-index.log \ + tip-index.aux + +tip-index.ps : tip-index.dvi + dvips tip-index.dvi + +tip-index.dvi : tip-index.tex + latex tip-index.tex + +tip-index.tex : tip.texified header.tex footer.tex + cat header.tex tip.texified footer.tex > tip-index.tex + +tip.texified : tip.eign tip.forgptx Makefile + gptx -f -r -i ./tip.eign -T < tip.forgptx | x.pl > tip.texified + +tip.eign : /usr/lib/eign exclude-words + cat /usr/lib/eign exclude-words > tip.eign + +screenlist : tip.texified + cat tip.texified \ + | gawk -F\{ '{count[$$4]++} \ + END {for (s in count) printf("%d %20s\n", count[s], s)}' \ + | tr -d '}' \ + | sort -n > screenlist + @echo "Check (say) the last 100 lines of ./screenlist". + +clean : + rm -f tip.eign tip.texified $(JUNKFILES) screenlist diff --git a/gnu/usr.bin/ptx/examples/ajay/README b/gnu/usr.bin/ptx/examples/ajay/README new file mode 100644 index 000000000000..7b55ca2fbf47 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/README @@ -0,0 +1,41 @@ +To: pinard@iro.umontreal.ca +Subject: Re: Gptx suggestions and help request +Date: Tue, 28 Sep 93 11:30:04 +0500 +From: ajayshah@cmie.ernet.in + +[...] My plaintext input looks like: "pagenum multiword-phrase" where +the multiword phrase is atmost five words. So [...], I'm doing two +columns in small type. + +I got one of the programmers here to write me a tex macro for my +problem. When it goes into production I'll mail you a few files: a +sample input, the gptx command, the output, and the tex macro. If you +find these interesting you can ship them with future gptx releases. + +Thanks a lot for gptx. If you have a mailing list of loyal users, +you can add us to it :-) + + +To: pinard@iro.umontreal.ca +Cc: rk@cmie.ernet.in +Subject: All glue code I used with gptx +Date: Tue, 05 Oct 93 15:23:44 +0500 +From: ajayshah@zigma.cmie.ernet.in + +That is a full set of a files for an example of "production use". You +are welcome to post them, or use them as a sample supplied with the +gptx distribution, etc., with absolutely no restrictions on what +anyone does with this. In case you do so, please acknowledge the +contribution of Rakesh Chauhan, rk@cmie.ernet.in, who is the author of +x.pl and header.tex. [...] + +As you can tell, I used it for a 100% realworld problem, and it +worked. Thanks a million. If you'd like, I can send you a hardcopy +of the full finished document (just send me your mailing address). If +you would like to mention the name of this document when you use +these files as a demo, it is + + Trends in Industrial Production + September 1993 + Centre for Monitoring Indian Economy, Bombay, India. + diff --git a/gnu/usr.bin/ptx/examples/ajay/footer.tex b/gnu/usr.bin/ptx/examples/ajay/footer.tex new file mode 100644 index 000000000000..6b47932f52ba --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/footer.tex @@ -0,0 +1 @@ +\end{document} diff --git a/gnu/usr.bin/ptx/examples/ajay/header.tex b/gnu/usr.bin/ptx/examples/ajay/header.tex new file mode 100644 index 000000000000..04a9c644802a --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/header.tex @@ -0,0 +1,21 @@ +\documentstyle [twocolumn,a4]{article} + +\pagestyle{empty} + +\textwidth 6.8in +\oddsidemargin -.8in +\evensidemargin -.8in +\textheight 10in +\topmargin -1in +% \columnseprule 1pt + +\begin{document} + +\def\xx #1#2#3#4#5#6{\hbox to \hsize{% +\hbox to 1.4in{\hfill #2}\hskip .05in% +\hbox to .8in{\it #3\hfil}\hskip .05in% +\hbox to 1.4in{#4\hfil}\hskip .05in% +\hbox{\hfil #6}\hfil}% +} + +\scriptsize diff --git a/gnu/usr.bin/ptx/examples/ajay/tip.forgptx b/gnu/usr.bin/ptx/examples/ajay/tip.forgptx new file mode 100644 index 000000000000..ecf6e0e5e893 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/tip.forgptx @@ -0,0 +1,10 @@ +1 Zinc concentrate +1 Coal +1 Ball clay +1 Non-coking coal +1 Calcareous sand +1 Natural Gas +1 Chalk +1 Bauxite +1 Clay (others) +1 Copper ore diff --git a/gnu/usr.bin/ptx/examples/ajay/x.pl b/gnu/usr.bin/ptx/examples/ajay/x.pl new file mode 100644 index 000000000000..e0615ba0f666 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ajay/x.pl @@ -0,0 +1,22 @@ +#! /usr/local/bin/perl + +while ($l = <>) +{ +chop $l; + +$l =~ s/\\xx //; +$l =~ s/}{/|/g; +$l =~ s/{//g; +$l =~ s/}//g; +@x = split(/\|/, $l); + +printf ("\\xx "); +for ($i = 0; $i <= $#x; $i++) + { + $v = substr($x[$i], 0, 17); + $v =~ s/\\$//; + printf("{%s}", $v); + } +printf ("\n"); + +} diff --git a/gnu/usr.bin/ptx/examples/ignore/README b/gnu/usr.bin/ptx/examples/ignore/README new file mode 100644 index 000000000000..33ee19ecb389 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ignore/README @@ -0,0 +1,65 @@ +From beebe@math.utah.edu Wed Oct 27 19:37:22 1993 +Date: Tue, 26 Oct 93 15:43:19 MDT +From: "Nelson H. F. Beebe" <beebe@math.utah.edu> +To: pinard@iro.umontreal.ca +Subject: Re: Another short comment on gptx 0.2 + +/usr/lib/eign: DECstation 5000, ULTRIX 4.3 + HP 9000/735, HP-UX 9.0 + IBM RS/6000, AIX 2.3 + IBM 3090, AIX MP370 2.1 + Stardent 1520, OS 2.2 + Sun SPARCstation, SunOS 4.x + +No eign anywhere on: HP 375, BSD 4.3 (ptx.c is in /usr/src/usr.bin, + and the source code refers to /usr/lib/eign, + but I could not find it in the source tree) + NeXT, Mach 3.0 (though documented in man pages) + Sun SPARCstation, Solaris 2.x + SGI Indigo, IRIX 4.0.x + +The contents of the eign files that I found on the above machines were +almost identical. With the exception of the Stardent and the IBM +3090, there were only two such files, one with 150 words, and the +other with 133, with only a few differences between them (some words +in the 133-word file were not in the 150-word file). I found the +133-word variant in groff-1.06/src/indxbib. I used archie to search +for eign, and it found 7 sites, all with the groff versions. + +The Stardent and IBM 3090 eign files have the same contents as the +150-word version, but have a multiline copyright comment at the +beginning. None of the others contains a copyright. + +I recently had occasion to build a similar list of words for bibindex, +which indexes a BibTeX .bib file, and for which omission of common +words, like articles and prepositions, helps to reduce the size of the +index. I didn't use eign to build that list, but instead, went +through the word lists from 3.8MB of .bib files in the tuglib +collection on ftp.math.utah.edu:pub/tex/bib, and collected words to be +ignored. That list includes words from several languages. I'll leave +it up to you to decide whether you wish to merge them or not; I +suspect it may be a better design choice to keep a separate eign file +for each language, although in my own application of ptx-ing +bibliographies, the titles do occur in multiple languages, so a +mixed-language eign is appropriate. Since there are standard ISO +2-letter abbreviations for every country, perhaps one could have +eign.xy for country xy (of course, only approximately is country == +language). The exact list of words in eign is not so critical; its +only purpose is to reduce the size of the output by not indexing words +that occur very frequently and have little content in themselves. + +I'm enclosing a shar bundle at the end of this message with the merger +of the multiple eign versions (duplicates eliminated, and the list +sorted into 179 unique words), followed by the bibindex list. + + + +======================================================================== +Nelson H. F. Beebe Tel: +1 801 581 5254 +Center for Scientific Computing FAX: +1 801 581 4148 +Department of Mathematics, 105 JWB Internet: beebe@math.utah.edu +University of Utah +Salt Lake City, UT 84112, USA +======================================================================== + + diff --git a/gnu/usr.bin/ptx/examples/ignore/bix b/gnu/usr.bin/ptx/examples/ignore/bix new file mode 100644 index 000000000000..b9a8ba69adef --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ignore/bix @@ -0,0 +1,109 @@ +ab +aber +als +an +and +are +as +auf +aus +az +bei +bir +but +da +das +dat +de +dei +dem +den +der +des +det +di +die +dos +een +eene +egy +ei +ein +eine +einen +einer +eines +eit +el +en +er +es +et +ett +eyn +eyne +for +from +fuer +fur +gl +gli +ha +haben +had +hai +has +hat +have +he +heis +hen +hena +henas +het +hin +hinar +hinir +hinn +hith +ho +hoi +il +in +ist +ka +ke +la +las +le +les +lo +los +mia +mit +na +nji +not +oder +of +on +or +os +others +sie +sind +so +ta +the +to +um +uma +un +una +und +une +uno +unter +von +with +yr diff --git a/gnu/usr.bin/ptx/examples/ignore/eign b/gnu/usr.bin/ptx/examples/ignore/eign new file mode 100644 index 000000000000..0401245ed007 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/ignore/eign @@ -0,0 +1,163 @@ +a +about +after +against +all +also +an +and +another +any +are +as +at +back +be +because +been +before +being +between +both +but +by +came +can +come +could +current +day +did +do +down +each +end +even +first +for +from +get +go +good +great +had +has +have +he +her +here +him +his +how +i +if +in +into +is +it +its +just +know +last +life +like +little +long +made +make +man +many +may +me +men +might +more +most +mr +much +must +my +name +never +new +no +not +now +of +off +old +on +one +only +or +other +our +out +over +own +part +people +point +right +said +same +say +see +she +should +since +so +some +start +state +still +such +take +than +that +the +their +them +then +there +these +they +this +those +three +through +time +to +too +true +try +two +under +up +us +use +used +value +very +was +way +we +well +were +what +when +where +which +while +who +why +will +with +without +work +world +would +year +years +you +your diff --git a/gnu/usr.bin/ptx/examples/include.pl b/gnu/usr.bin/ptx/examples/include.pl new file mode 100755 index 000000000000..cb3c0ffe5263 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/include.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl -- # -*-Perl-*- +eval "exec /usr/bin/perl -S $0 $*" + if $running_under_some_shell; + +# Construct a permuted index for all system include files. +# Copyright (C) 1991 Free Software Foundation, Inc. +# Francois Pinard <pinard@iro.umontreal.ca>, June 1991. + +# NOTE: about removing asm statements? +# NOTE: about removing strings? +# NOTE: about ignoring 0xHEXDIGITS, unchar/ushort/etc. + +# Construct a sorted list of system include files. + +opendir (DIR, "/usr/include"); +@includes = sort grep (-f "/usr/include/$_", readdir (DIR)); +opendir (DIR, "/usr/include/sys"); +foreach (sort grep (-f "/usr/include/sys/$_", readdir (DIR))) { + push (@includes, "sys/$_"); +} +closedir (DIR); + +# Launch the permuted indexer, with a list of ignore words. + +$ignore = "/tmp/incptx.$$"; +open (IGNORE, "> $ignore"); +print IGNORE join ("\n", split (' ', <<IGNORE)), "\n"; +asm at at386 break bss case ch char continue copyright corporation +default define defined do double dst else endif enum extern file flag +float for goto i286 i386 ident if ifdef ifndef int interactive len +lint long m32 mpat num pdp11 printf ptr register return sco5 short siz +sizeof src static str struct sun switch sys systems type typedef u370 +u3b u3b15 u3b2 u3b5 undef union unsigned vax void while win +IGNORE +close IGNORE; +exit 0; + +open (OUTPUT, "| ptx -r -f -W '[a-zA-Z_][a-zA-Z_0-9]+' -F ... -i $ignore") + || die "ptx did not start\n"; +select (OUTPUT); + +# Reformat all files, removing C comments and adding a reference field. + +foreach $include (@includes) +{ + warn "Reading /usr/include/$include\n"; + open (INPUT, "/usr/include/$include"); + while (<INPUT>) + { + + # Get rid of comments. + + $comment = $next_comment; + if ($comment) + { + $next_comment = !s,^.*\*/,,; + } + else + { + s,/\*.*\*/,,g; + $next_comment = s,/\*.*,,; + } + next if $comment && $next_comment; + + # Remove extraneous white space. + + s/[ \t]+/ /g; + s/ $//; + next if /^$/; + + # Print the line with its reference. + + print "$include($.): ", $_; + } +} + +warn "All read, now ptx' game!\n"; +close OUTPUT || die "ptx failed...\n"; +unlink $ignore; diff --git a/gnu/usr.bin/ptx/examples/latex/Makefile b/gnu/usr.bin/ptx/examples/latex/Makefile new file mode 100644 index 000000000000..5f930b2c7d0e --- /dev/null +++ b/gnu/usr.bin/ptx/examples/latex/Makefile @@ -0,0 +1,15 @@ +# Example of using ptx with latex. +# Copyright (C) 1993 Free Software Foundation, Inc. +# Francois Pinard <pinard@iro.umontreal.ca>, 1993. + +PTX = ../ptx +PTX_OPTIONS = -AfTWi.i + +try: latex.dvi + xdvi latex + +latex.dvi: latex.tex table.tex + latex latex + +table.tex: Makefile ../COPYING + $(PTX) $(PTX_OPTIONS) ../COPYING | sed 's///' > table.tex diff --git a/gnu/usr.bin/ptx/examples/latex/README b/gnu/usr.bin/ptx/examples/latex/README new file mode 100644 index 000000000000..fc5098a8dd49 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/latex/README @@ -0,0 +1,10 @@ +Date: Sun, 26 Sep 93 19:07:10 EDT +From: Francois Pinard <pinard@iro.umontreal.ca> +To: ajayshah@cmie.ernet.in +Subject: Re: Gptx suggestions and help request + + In fact, if you could send me such a macro right now I would be + thrilled :-) + +Ok, I worked out this example for you. Even if a little rude, you can +still start from it for your own need. [...] diff --git a/gnu/usr.bin/ptx/examples/latex/latex.tex b/gnu/usr.bin/ptx/examples/latex/latex.tex new file mode 100644 index 000000000000..1f0a2f10bb1d --- /dev/null +++ b/gnu/usr.bin/ptx/examples/latex/latex.tex @@ -0,0 +1,11 @@ +\documentstyle[11pt]{article} +\begin{document} + +\def\xx#1#2#3#4#5#6{\hbox{ + \hbox to2.5in{\hfil#5#2} + \hbox to3.0in{{\sl #3}\,#4#1\hfil} + \hbox to1.5in{\tiny#6\hfil} +}} +\input table + +\end{document} diff --git a/gnu/usr.bin/ptx/examples/latex/table.tex b/gnu/usr.bin/ptx/examples/latex/table.tex new file mode 100644 index 000000000000..b68ea38d7ca0 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/latex/table.tex @@ -0,0 +1,65 @@ +\xx {}{ate to certain respons}{ibi}{lities for you if you}{}{../COPYING:30} +\xx {}{These actions are proh}{ibi}{ted by law if you do n}{}{../COPYING:183} +\xx {}{EN ADVISED OF THE POSS}{IBI}{LITY OF SUCH DAMAGES.}{}{../COPYING:278} +\xx {}{icense may add an expl}{ici}{t geographical distrib}{}{../COPYING:232} +\xx {}{OF ALL NECESSARY SERV}{ICI}{NG, REPAIR OR CORRECTI}{}{../COPYING:267} +\xx {}{aims or to contest val}{idi}{ty of any such claims;}{}{../COPYING:216} +\xx {}{If the software is mod}{ifi}{ed by someone else and}{}{../COPYING:45} +\xx {}{, distribution and mod}{ifi}{cation follow.}{pying}{../COPYING:57} +\xx {}{, DISTRIBUTION AND MOD}{IFI}{CATION 0. This Lice}{}{../COPYING:60} +\xx {}{r verbatim or with mod}{ifi}{cations and/or transla}{}{../COPYING:68} +\xx {}{ation in the term "mod}{ifi}{cation".)}{t limit}{../COPYING:70} +\xx {}{, distribution and mod}{ifi}{cation are not covered}{}{../COPYING:72} +\xx {}{nd distribute such mod}{ifi}{cations or work under}{}{../COPYING:92} +\xx {}{You must cause the mod}{ifi}{ed files to carry prom}{}{../COPYING:95} +\xx {ads c}{c) If the mod}{ifi}{ed program normally re}{}{../COPYING:103} +\xx {}{ments apply to the mod}{ifi}{ed work as a whole.}{}{../COPYING:114} +\xx {work are n}{If ident}{ifi}{able sections of that}{}{../COPYING:115} +\xx {}{he work for making mod}{ifi}{cations to it.}{of t}{../COPYING:156} +\xx {}{If the Program spec}{ifi}{es a version number of}{}{../COPYING:243} +\xx {}{hey have is not the or}{igi}{nal, so that any probl}{}{../COPYING:46} +\xx {}{not reflect on the or}{igi}{nal authors' reputatio}{}{../COPYING:47} +\xx {}{a license from the or}{igi}{nal licensor to copy,}{}{../COPYING:191} +\xx {}{ted interfaces, the or}{igi}{nal copyright holder w}{}{../COPYING:231} +\xx {}{RRANTIES OF MERCHANTAB}{ILI}{TY AND FITNESS FOR A P}{}{../COPYING:265} +\xx {}{OUT OF THE USE OR INAB}{ILI}{TY TO USE THE PROGRAM}{}{../COPYING:274} +\xx {}{anty of MERCHANTAB}{ILI}{TY or FITNESS FOR A PA}{}{../COPYING:303} +\xx {}{is included without l}{imi}{tation in the term "mo}{}{../COPYING:69} +\xx {}{ny other reason (not l}{imi}{ted to patent issues),}{}{../COPYING:198} +\xx {}{aphical distribution l}{imi}{tation excluding those}{}{../COPYING:232} +\xx {}{nse incorporates the l}{imi}{tation as if written i}{}{../COPYING:235} +\xx {}{new versions will be s}{imi}{lar in spirit to the p}{}{../COPYING:239} +\xx {}{, INCLUDING, BUT NOT L}{IMI}{TED TO, THE IMPLIED WA}{}{../COPYING:264} +\xx {}{M (INCLUDING BUT NOT L}{IMI}{TED TO LOSS OF DATA OR}{}{../COPYING:274} +\xx {}{s to say, a work conta}{ini}{ng the Program or a po}{}{../COPYING:67} +\xx {}{sociated interface def}{ini}{tion files, plus the s}{}{../COPYING:158} +\xx {}{you must give the rec}{ipi}{ents all the rights th}{}{../COPYING:34} +\xx {}{ed on, we want its rec}{ipi}{ents to know that what}{}{../COPYING:46} +\xx {}{and give any other rec}{ipi}{ents of the Program a}{}{../COPYING:84} +\xx {}{the Program), the rec}{ipi}{ent automatically rece}{}{../COPYING:190} +\xx {}{estrictions on the rec}{ipi}{ents' exercise of the}{}{../COPYING:193} +\xx {}{will be similar in sp}{iri}{t to the present versi}{}{../COPYING:239} +\xx {he two goal}{Our dec}{isi}{on will be guided by t}{}{../COPYING:254} +\xx {}{NSEQUENTIAL DAMAGES AR}{ISI}{NG OUT OF THE USE OR I}{}{../COPYING:273} +\xx {}{tive mode: Gnomov}{isi}{on version 69, Copyrig}{}{../COPYING:315} +\xx {}{e of author Gnomov}{isi}{on comes with ABSOLUTE}{}{../COPYING:316} +\xx {}{the program `Gnomov}{isi}{on' (which makes passe}{}{../COPYING:330} +\xx {}{to certain responsibil}{iti}{es for you if you dist}{}{../COPYING:30} +\xx {}{precise terms and cond}{iti}{ons for copying, distr}{}{../COPYING:56} +\xx {}{ENSE TERMS AND COND}{ITI}{ONS FOR COPYING, DISTR}{}{../COPYING:60} +\xx {}{meet all of these cond}{iti}{ons: a) You must}{}{../COPYING:93} +\xx {}{m under these cond}{iti}{ons, and telling the u}{}{../COPYING:109} +\xx {f another wo}{In add}{iti}{on, mere aggregation o}{}{../COPYING:129} +\xx {}{all its terms and cond}{iti}{ons for copying, distr}{}{../COPYING:186} +\xx {}{o these terms and cond}{iti}{ons.}{bject t}{../COPYING:192} +\xx {}{o patent issues), cond}{iti}{ons are imposed on you}{}{../COPYING:199} +\xx {}{at contradict the cond}{iti}{ons of this License, t}{}{../COPYING:200} +\xx {}{cuse you from the cond}{iti}{ons of this License.}{}{../COPYING:201} +\xx {}{ing the terms and cond}{iti}{ons either of that ver}{}{../COPYING:244} +\xx {}{hose distribution cond}{iti}{ons are different, wri}{}{../COPYING:251} +\xx {}{OTHERWISE STATED IN WR}{ITI}{NG THE COPYRIGHT HOLDE}{}{../COPYING:262} +\xx {}{LAW OR AGREED TO IN WR}{ITI}{NG WILL ANY COPYRIGHT}{}{../COPYING:270} +\xx {}{END OF TERMS AND COND}{ITI}{ONS Appendix: How t}{}{../COPYING:280} +\xx {}{under certain cond}{iti}{ons; type `show c' for}{}{../COPYING:318} +\xx {}{free program will ind}{ivi}{dually obtain patent l}{}{../COPYING:52} +\xx {g, distribution}{Act}{ivi}{ties other than copyin}{}{../COPYING:72} diff --git a/gnu/usr.bin/ptx/examples/luke/README b/gnu/usr.bin/ptx/examples/luke/README new file mode 100644 index 000000000000..62918611d4f4 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/luke/README @@ -0,0 +1,2 @@ +From: Luke Kendall <luke@research.canon.oz.au> +Date: Wed, 16 Oct 91 12:26:39 EST diff --git a/gnu/usr.bin/ptx/examples/luke/xxroff.sh b/gnu/usr.bin/ptx/examples/luke/xxroff.sh new file mode 100644 index 000000000000..55ef90826e49 --- /dev/null +++ b/gnu/usr.bin/ptx/examples/luke/xxroff.sh @@ -0,0 +1,108 @@ +#!/bin/sh +# +# Author: Luke Kendall +# +MYNAME=`basename $0` +usage="usage: $MYNAME [man-directory] + (generates permuted index of -man files in directory)" +md=/usr/man +# +if [ $# = 0 ] +then + echo "$MYNAME: no man directory specified: assuming $md" +elif [ $# != 1 ] +then + echo "$usage" + exit 1 +elif [ -d $1 ] +then + md="$1" +else + echo "$usage" + exit 1 +fi +echo "Permuted index of $md:" +out=ptx.tr +# ------ clumsy permuted index macros (replaced by stuff below) ------------ +cat <<'EOF' > $out +.pn 1 +.de xx +\\$1 \\$2 \\fB\\$3\\fR \\$4 \\s-1\\$5\\s0 +.. +.pl 10i +.de NP +.ev 1 +.ft 1 +.ps 10 +.sp 0.75c +.tl '\s-2\\fIpermuted index\\fP\s0'\- \\n% \-'\s-2\\fIpermuted index\\fP\s0' +.pn +1 +.bp +.ev +.. +.wh 9i NP +.nf +.na +.ta 6.5i-1.1iR 6.5iR 6.51iR 6.52R +.ll 6.0i +.po 0i +.sp 0.25i +'\" +EOF +# ------ ------- ------- ------- ------- ------- +# ------ alternate permuted index macros (from net) ------------ +cat <<'EOF' > $out +.pl 10i +.de NP +.ev 1 +.ft 1 +.ps 10 +.sp 0.75c +.tl '\s-2\\fIpermuted index\\fP\s0'\- \\n% \-'\s-2\\fIpermuted index\\fP\s0' +.pn +1 +.bp +.ev +.. +.wh 9i NP +.po 0.5i +.sp 0.25i +.tr ~ \" tildes will translate to blanks +'\".ll 80 \" line length of output +.ll 6.0i \" line length of output +.nf \" must be in no-fill mode +.nr )r \n(.lu-10n \" set position of reference in line (10 less than length) +.nr )k \n()ru/2u \" set position of keyword (approx. centered) +.ds s2 ~~~ \" this is the center gap -- 3 spaces +.de xx \"definition of xx macro +.ds s1\" \" initialise to null string +.if \w@\\$2@ .ds s1 ~\" \"set to single blank if there is second arg +.ds s3\" \" initialise to null string +.if \w@\\$4@ .ds s3 ~\" \"set to single blank if there is second arg +.ds s4 ~\" \" set to single blank +.ds s5 ~\" \" set to single blank +.ds y \\*(s4\a\\*(s5\" \" blank, leader, blank +.ta \\n()ru-\w@\\*(s5@u \" set tab just to left of ref +\h@\\n()ku-\w@\\$1\\*(s1\\$2\\*(s2@u@\\$1\\*(s1\\$2\\*(s2\\$3\\*(s3\\$4\\*y\\$5 +.. + ~ +EOF +# ------ ------- ------- ------- ------- ------- +find $md -type f -name "*.[1-8nl]*" -print | +while read f +do + man=`basename $f` + man=`expr "$man" : "\(.*\)\.[^\.]*"` +echo $man: + # + # Use 1st non-"." and non-"'" started line as input to ptx (this + # should be the synopsis after the `.SH NAME'); + # strip any "\-" from it (a silly sort key for ptx to avoid); + # insert a leading man page name for the -r option to find + # + sed -n '/^[^.]/s/\\-//g;/^[^.]/p;/^[^.]/q' $f | sed "s/^/($man) /" +done | ptx -t -f -r >> $out +# +# Turn the troff'able permuted index file into PostScript +# +psroff -t -rL10i $out > ptx.ps +echo "$out and ptx.ps produced from man directory $md." diff --git a/gnu/usr.bin/ptx/getopt.c b/gnu/usr.bin/ptx/getopt.c new file mode 100644 index 000000000000..7a4673b8d8db --- /dev/null +++ b/gnu/usr.bin/ptx/getopt.c @@ -0,0 +1,757 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. + (Supposedly there are some machines where it might get a warning, + but changing this conditional to __STDC__ is too risky.) */ +#ifdef __GNUC__ +#ifdef IN_GCC +#include "gstddef.h" +#else +#include <stddef.h> +#endif +extern size_t strlen (const char *); +#endif + +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnu/usr.bin/ptx/getopt.h b/gnu/usr.bin/ptx/getopt.h new file mode 100644 index 000000000000..45541f5ac0f9 --- /dev/null +++ b/gnu/usr.bin/ptx/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/gnu/usr.bin/ptx/getopt1.c b/gnu/usr.bin/ptx/getopt1.c new file mode 100644 index 000000000000..f784b5757c59 --- /dev/null +++ b/gnu/usr.bin/ptx/getopt1.c @@ -0,0 +1,187 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#include "getopt.h" + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnu/usr.bin/ptx/mkinstalldirs b/gnu/usr.bin/ptx/mkinstalldirs new file mode 100755 index 000000000000..0e2937731092 --- /dev/null +++ b/gnu/usr.bin/ptx/mkinstalldirs @@ -0,0 +1,35 @@ +#!/bin/sh +# Make directory hierarchy. +# Written by Noah Friedman <friedman@prep.ai.mit.edu> +# Public domain. + +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +errstatus=0 + +for file in ${1+"$@"} ; do + oIFS="${IFS}" + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo ${file} | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS="${oIFS}" + + pathcomp='' + + for d in ${1+"$@"} ; do + pathcomp="${pathcomp}${d}" + + if test ! -d "${pathcomp}"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "${pathcomp}" || errstatus=$? + fi + + pathcomp="${pathcomp}/" + done +done + +exit $errstatus + +# eof diff --git a/gnu/usr.bin/ptx/ptx.c b/gnu/usr.bin/ptx/ptx.c new file mode 100644 index 000000000000..2dc306e97150 --- /dev/null +++ b/gnu/usr.bin/ptx/ptx.c @@ -0,0 +1,2237 @@ +/* Permuted index for GNU, with keywords in their context. + Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc. + Francois Pinard <pinard@iro.umontreal.ca>, 1988. + + 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, 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +const char *version_string = "GNU ptx version 0.3"; + +char *const copyright = "\ +This program is free software; you can redistribute it and/or modify\n\ +it under the terms of the GNU General Public License as published by\n\ +the Free Software Foundation; either version 2, or (at your option)\n\ +any later version.\n\ +\n\ +This program is distributed in the hope that it will be useful,\n\ +but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ +GNU General Public License for more details.\n\ +\n\ +You should have received a copy of the GNU General Public License\n\ +along with this program; if not, write to the Free Software\n\ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; + +/* Reallocation step when swallowing non regular files. The value is not + the actual reallocation step, but its base two logarithm. */ +#define SWALLOW_REALLOC_LOG 12 + +/* Imported from "regex.c". */ +#define Sword 1 + +#ifdef STDC_HEADERS + +#include <stdlib.h> +#include <ctype.h> + +#else /* not STDC_HEADERS */ + +/* These definitions work, for all 256 characters. */ +#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define isxdigit(c) \ + (((unsigned char) (c) >= 'a' && (unsigned char) (c) <= 'f') \ + || ((unsigned char) (c) >= 'A' && (unsigned char) (c) <= 'F') \ + || ((unsigned char) (c) >= '0' && (unsigned char) (c) <= '9')) +#define islower(c) ((unsigned char) (c) >= 'a' && (unsigned char) (c) <= 'z') +#define isupper(c) ((unsigned char) (c) >= 'A' && (unsigned char) (c) <= 'Z') +#define isalpha(c) (islower (c) || isupper (c)) +#define toupper(c) (islower (c) ? (c) - 'a' + 'A' : (c)) + +#endif /* not STDC_HEADERS */ + +#if !defined (isascii) || defined (STDC_HEADERS) +#undef isascii +#define isascii(c) 1 +#endif + +#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) +#define ISODIGIT(c) ((c) >= '0' && (c) <= '7') +#define HEXTOBIN(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') +#define OCTTOBIN(c) ((c) - '0') + +#include <stdio.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#if !defined(S_ISREG) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#else /* not HAVE_STRING_H */ +#include <strings.h> +#define strchr index +#define strrchr rindex +#endif /* not HAVE_STRING_H */ + +#include "getopt.h" + +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +#include "bumpalloc.h" +#include "diacrit.h" +#include "regex.h" + +#ifndef __STDC__ +void *xmalloc (); +void *xrealloc (); +#else +void *xmalloc (int); +void *xrealloc (void *, int); +#endif + + +/* Global definitions. */ + +const char *program_name; /* name of this program */ +static int show_help = 0; /* display usage information and exit */ +static int show_version = 0; /* print the version and exit */ + +/* Program options. */ + +enum Format +{ + DUMB_FORMAT, /* output for a dumb terminal */ + ROFF_FORMAT, /* output for `troff' or `nroff' */ + TEX_FORMAT, /* output for `TeX' or `LaTeX' */ + UNKNOWN_FORMAT /* output format still unknown */ +}; + +int gnu_extensions = 1; /* trigger all GNU extensions */ +int auto_reference = 0; /* references are `file_name:line_number:' */ +int input_reference = 0; /* references at beginning of input lines */ +int right_reference = 0; /* output references after right context */ +int line_width = 72; /* output line width in characters */ +int gap_size = 3; /* number of spaces between output fields */ +const char *truncation_string = "/"; + /* string used to mark line truncations */ +const char *macro_name = "xx"; /* macro name for roff or TeX output */ +enum Format output_format = UNKNOWN_FORMAT; + /* output format */ + +int ignore_case = 0; /* fold lower to upper case for sorting */ +const char *context_regex_string = NULL; + /* raw regex for end of context */ +const char *word_regex_string = NULL; + /* raw regex for a keyword */ +const char *break_file = NULL; /* name of the `Break characters' file */ +const char *only_file = NULL; /* name of the `Only words' file */ +const char *ignore_file = NULL; /* name of the `Ignore words' file */ + +/* A BLOCK delimit a region in memory of arbitrary size, like the copy of a + whole file. A WORD is something smaller, its length should fit in a + short integer. A WORD_TABLE may contain several WORDs. */ + +typedef struct + { + char *start; /* pointer to beginning of region */ + char *end; /* pointer to end + 1 of region */ + } +BLOCK; + +typedef struct + { + char *start; /* pointer to beginning of region */ + short size; /* length of the region */ + } +WORD; + +typedef struct + { + WORD *start; /* array of WORDs */ + size_t length; /* number of entries */ + } +WORD_TABLE; + +/* Pattern description tables. */ + +/* For each character, provide its folded equivalent. */ +unsigned char folded_chars[CHAR_SET_SIZE]; + +/* For each character, indicate if it is part of a word. */ +char syntax_table[CHAR_SET_SIZE]; +char *re_syntax_table = syntax_table; + +/* Compiled regex for end of context. */ +struct re_pattern_buffer *context_regex; + +/* End of context pattern register indices. */ +struct re_registers context_regs; + +/* Compiled regex for a keyword. */ +struct re_pattern_buffer *word_regex; + +/* Keyword pattern register indices. */ +struct re_registers word_regs; + +/* A word characters fastmap is used only when no word regexp has been + provided. A word is then made up of a sequence of one or more characters + allowed by the fastmap. Contains !0 if character allowed in word. Not + only this is faster in most cases, but it simplifies the implementation + of the Break files. */ +char word_fastmap[CHAR_SET_SIZE]; + +/* Maximum length of any word read. */ +int maximum_word_length; + +/* Maximum width of any reference used. */ +int reference_max_width; + + +/* Ignore and Only word tables. */ + +WORD_TABLE ignore_table; /* table of words to ignore */ +WORD_TABLE only_table; /* table of words to select */ + +#define ALLOC_NEW_WORD(table) \ + BUMP_ALLOC ((table)->start, (table)->length, 8, WORD) + +/* Source text table, and scanning macros. */ + +int number_input_files; /* number of text input files */ +int total_line_count; /* total number of lines seen so far */ +const char **input_file_name; /* array of text input file names */ +int *file_line_count; /* array of `total_line_count' values at end */ + +BLOCK text_buffer; /* file to study */ +char *text_buffer_maxend; /* allocated end of text_buffer */ + +/* SKIP_NON_WHITE used only for getting or skipping the reference. */ + +#define SKIP_NON_WHITE(cursor, limit) \ + while (cursor < limit && !isspace(*cursor)) \ + cursor++ + +#define SKIP_WHITE(cursor, limit) \ + while (cursor < limit && isspace(*cursor)) \ + cursor++ + +#define SKIP_WHITE_BACKWARDS(cursor, start) \ + while (cursor > start && isspace(cursor[-1])) \ + cursor-- + +#define SKIP_SOMETHING(cursor, limit) \ + do \ + if (word_regex_string) \ + { \ + int count; \ + count = re_match (word_regex, cursor, limit - cursor, 0, NULL); \ + cursor += count <= 0 ? 1 : count; \ + } \ + else if (word_fastmap[(unsigned char) *cursor]) \ + while (cursor < limit && word_fastmap[(unsigned char) *cursor]) \ + cursor++; \ + else \ + cursor++; \ + while (0) + +/* Occurrences table. + + The `keyword' pointer provides the central word, which is surrounded + by a left context and a right context. The `keyword' and `length' + field allow full 8-bit characters keys, even including NULs. At other + places in this program, the name `keyafter' refers to the keyword + followed by its right context. + + The left context does not extend, towards the beginning of the file, + further than a distance given by the `left' value. This value is + relative to the keyword beginning, it is usually negative. This + insures that, except for white space, we will never have to backward + scan the source text, when it is time to generate the final output + lines. + + The right context, indirectly attainable through the keyword end, does + not extend, towards the end of the file, further than a distance given + by the `right' value. This value is relative to the keyword + beginning, it is usually positive. + + When automatic references are used, the `reference' value is the + overall line number in all input files read so far, in this case, it + is of type (int). When input references are used, the `reference' + value indicates the distance between the keyword beginning and the + start of the reference field, it is of type (DELTA) and usually + negative. */ + +typedef short DELTA; /* to hold displacement within one context */ + +typedef struct + { + WORD key; /* description of the keyword */ + DELTA left; /* distance to left context start */ + DELTA right; /* distance to right context end */ + int reference; /* reference descriptor */ + } +OCCURS; + +/* The various OCCURS tables are indexed by the language. But the time + being, there is no such multiple language support. */ + +OCCURS *occurs_table[1]; /* all words retained from the read text */ +size_t number_of_occurs[1]; /* number of used slots in occurs_table */ + +#define ALLOC_NEW_OCCURS(language) \ + BUMP_ALLOC (occurs_table[language], number_of_occurs[language], 9, OCCURS) + + +/* Communication among output routines. */ + +/* Indicate if special output processing is requested for each character. */ +char edited_flag[CHAR_SET_SIZE]; + +int half_line_width; /* half of line width, reference excluded */ +int before_max_width; /* maximum width of before field */ +int keyafter_max_width; /* maximum width of keyword-and-after field */ +int truncation_string_length; /* length of string used to flag truncation */ + +/* When context is limited by lines, wraparound may happen on final output: + the `head' pointer gives access to some supplementary left context which + will be seen at the end of the output line, the `tail' pointer gives + access to some supplementary right context which will be seen at the + beginning of the output line. */ + +BLOCK tail; /* tail field */ +int tail_truncation; /* flag truncation after the tail field */ + +BLOCK before; /* before field */ +int before_truncation; /* flag truncation before the before field */ + +BLOCK keyafter; /* keyword-and-after field */ +int keyafter_truncation; /* flag truncation after the keyafter field */ + +BLOCK head; /* head field */ +int head_truncation; /* flag truncation before the head field */ + +BLOCK reference; /* reference field for input reference mode */ + + +/* Miscellaneous routines. */ + +/*------------------------------------------------------. +| Duplicate string STRING, while evaluating \-escapes. | +`------------------------------------------------------*/ + +/* Loosely adapted from GNU shellutils printf.c code. */ + +char * +copy_unescaped_string (const char *string) +{ + char *result; /* allocated result */ + char *cursor; /* cursor in result */ + int value; /* value of \nnn escape */ + int length; /* length of \nnn escape */ + + result = xmalloc (strlen (string) + 1); + cursor = result; + + while (*string) + if (*string == '\\') + { + string++; + switch (*string) + { + case 'x': /* \xhhh escape, 3 chars maximum */ + value = 0; + for (length = 0, string++; + length < 3 && ISXDIGIT (*string); + length++, string++) + value = value * 16 + HEXTOBIN (*string); + if (length == 0) + { + *cursor++ = '\\'; + *cursor++ = 'x'; + } + else + *cursor++ = value; + break; + + case '0': /* \0ooo escape, 3 chars maximum */ + value = 0; + for (length = 0, string++; + length < 3 && ISODIGIT (*string); + length++, string++) + value = value * 8 + OCTTOBIN (*string); + *cursor++ = value; + break; + + case 'a': /* alert */ +#if __STDC__ + *cursor++ = '\a'; +#else + *cursor++ = 7; +#endif + string++; + break; + + case 'b': /* backspace */ + *cursor++ = '\b'; + string++; + break; + + case 'c': /* cancel the rest of the output */ + while (*string) + string++; + break; + + case 'f': /* form feed */ + *cursor++ = '\f'; + string++; + break; + + case 'n': /* new line */ + *cursor++ = '\n'; + string++; + break; + + case 'r': /* carriage return */ + *cursor++ = '\r'; + string++; + break; + + case 't': /* horizontal tab */ + *cursor++ = '\t'; + string++; + break; + + case 'v': /* vertical tab */ +#if __STDC__ + *cursor++ = '\v'; +#else + *cursor++ = 11; +#endif + string++; + break; + + default: + *cursor++ = '\\'; + *cursor++ = *string++; + break; + } + } + else + *cursor++ = *string++; + + *cursor = '\0'; + return result; +} + +/*-------------------------------------------------------------------. +| Compile the regex represented by STRING, diagnose and abort if any | +| error. Returns the compiled regex structure. | +`-------------------------------------------------------------------*/ + +struct re_pattern_buffer * +alloc_and_compile_regex (const char *string) +{ + struct re_pattern_buffer *pattern; /* newly allocated structure */ + const char *message; /* error message returned by regex.c */ + + pattern = (struct re_pattern_buffer *) + xmalloc (sizeof (struct re_pattern_buffer)); + memset (pattern, 0, sizeof (struct re_pattern_buffer)); + + pattern->buffer = NULL; + pattern->allocated = 0; + pattern->translate = ignore_case ? (char *) folded_chars : NULL; + pattern->fastmap = (char *) xmalloc (CHAR_SET_SIZE); + + message = re_compile_pattern (string, strlen (string), pattern); + if (message) + error (1, 0, "%s (for regexp `%s')", message, string); + + /* The fastmap should be compiled before `re_match'. The following + call is not mandatory, because `re_search' is always called sooner, + and it compiles the fastmap if this has not been done yet. */ + + re_compile_fastmap (pattern); + + /* Do not waste extra allocated space. */ + + if (pattern->allocated > pattern->used) + { + pattern->buffer + = (unsigned char *) xrealloc (pattern->buffer, pattern->used); + pattern->allocated = pattern->used; + } + + return pattern; +} + +/*------------------------------------------------------------------------. +| This will initialize various tables for pattern match and compiles some | +| regexps. | +`------------------------------------------------------------------------*/ + +void +initialize_regex (void) +{ + int character; /* character value */ + + /* Initialize the regex syntax table. */ + + for (character = 0; character < CHAR_SET_SIZE; character++) + syntax_table[character] = isalpha (character) ? Sword : 0; + + /* Initialize the case folding table. */ + + if (ignore_case) + for (character = 0; character < CHAR_SET_SIZE; character++) + folded_chars[character] = toupper (character); + + /* Unless the user already provided a description of the end of line or + end of sentence sequence, select an end of line sequence to compile. + If the user provided an empty definition, thus disabling end of line + or sentence feature, make it NULL to speed up tests. If GNU + extensions are enabled, use end of sentence like in GNU emacs. If + disabled, use end of lines. */ + + if (context_regex_string) + { + if (!*context_regex_string) + context_regex_string = NULL; + } + else if (gnu_extensions && !input_reference) + context_regex_string = "[.?!][]\"')}]*\\($\\|\t\\| \\)[ \t\n]*"; + else + context_regex_string = "\n"; + + if (context_regex_string) + context_regex = alloc_and_compile_regex (context_regex_string); + + /* If the user has already provided a non-empty regexp to describe + words, compile it. Else, unless this has already been done through + a user provided Break character file, construct a fastmap of + characters that may appear in a word. If GNU extensions enabled, + include only letters of the underlying character set. If disabled, + include almost everything, even punctuations; stop only on white + space. */ + + if (word_regex_string && *word_regex_string) + word_regex = alloc_and_compile_regex (word_regex_string); + else if (!break_file) + if (gnu_extensions) + { + + /* Simulate \w+. */ + + for (character = 0; character < CHAR_SET_SIZE; character++) + word_fastmap[character] = isalpha (character); + } + else + { + + /* Simulate [^ \t\n]+. */ + + memset (word_fastmap, 1, CHAR_SET_SIZE); + word_fastmap[' '] = 0; + word_fastmap['\t'] = 0; + word_fastmap['\n'] = 0; + } +} + +/*------------------------------------------------------------------------. +| This routine will attempt to swallow a whole file name FILE_NAME into a | +| contiguous region of memory and return a description of it into BLOCK. | +| Standard input is assumed whenever FILE_NAME is NULL, empty or "-". | +| | +| Previously, in some cases, white space compression was attempted while | +| inputting text. This was defeating some regexps like default end of | +| sentence, which checks for two consecutive spaces. If white space | +| compression is ever reinstated, it should be in output routines. | +`------------------------------------------------------------------------*/ + +void +swallow_file_in_memory (const char *file_name, BLOCK *block) +{ + int file_handle; /* file descriptor number */ + struct stat stat_block; /* stat block for file */ + int allocated_length; /* allocated length of memory buffer */ + int used_length; /* used length in memory buffer */ + int read_length; /* number of character gotten on last read */ + + /* As special cases, a file name which is NULL or "-" indicates standard + input, which is already opened. In all other cases, open the file from + its name. */ + + if (!file_name || !*file_name || strcmp (file_name, "-") == 0) + file_handle = fileno (stdin); + else + if ((file_handle = open (file_name, O_RDONLY)) < 0) + error (1, errno, file_name); + + /* If the file is a plain, regular file, allocate the memory buffer all at + once and swallow the file in one blow. In other cases, read the file + repeatedly in smaller chunks until we have it all, reallocating memory + once in a while, as we go. */ + + if (fstat (file_handle, &stat_block) < 0) + error (1, errno, file_name); + + if (S_ISREG (stat_block.st_mode)) + { + block->start = (char *) xmalloc ((int) stat_block.st_size); + + if (read (file_handle, block->start, (int) stat_block.st_size) + != stat_block.st_size) + error (1, errno, file_name); + + block->end = block->start + stat_block.st_size; + } + else + { + block->start = (char *) xmalloc (1 << SWALLOW_REALLOC_LOG); + used_length = 0; + allocated_length = (1 << SWALLOW_REALLOC_LOG); + + while ((read_length = read (file_handle, + block->start + used_length, + allocated_length - used_length)) > 0) + { + used_length += read_length; + if (used_length == allocated_length) + { + allocated_length += (1 << SWALLOW_REALLOC_LOG); + block->start + = (char *) xrealloc (block->start, allocated_length); + } + } + + if (read_length < 0) + error (1, errno, file_name); + + block->end = block->start + used_length; + } + + /* Close the file, but only if it was not the standard input. */ + + if (file_handle != fileno (stdin)) + close (file_handle); +} + +/* Sort and search routines. */ + +/*--------------------------------------------------------------------------. +| Compare two words, FIRST and SECOND, and return 0 if they are identical. | +| Return less than 0 if the first word goes before the second; return | +| greater than 0 if the first word goes after the second. | +| | +| If a word is indeed a prefix of the other, the shorter should go first. | +`--------------------------------------------------------------------------*/ + +int +compare_words (const void *void_first, const void *void_second) +{ +#define first ((WORD *) void_first) +#define second ((WORD *) void_second) + int length; /* minimum of two lengths */ + int counter; /* cursor in words */ + int value; /* value of comparison */ + + length = first->size < second->size ? first->size : second->size; + + if (ignore_case) + { + for (counter = 0; counter < length; counter++) + { + value = (folded_chars [(unsigned char) (first->start[counter])] + - folded_chars [(unsigned char) (second->start[counter])]); + if (value != 0) + return value; + } + } + else + { + for (counter = 0; counter < length; counter++) + { + value = ((unsigned char) first->start[counter] + - (unsigned char) second->start[counter]); + if (value != 0) + return value; + } + } + + return first->size - second->size; +#undef first +#undef second +} + +/*-----------------------------------------------------------------------. +| Decides which of two OCCURS, FIRST or SECOND, should lexicographically | +| go first. In case of a tie, preserve the original order through a | +| pointer comparison. | +`-----------------------------------------------------------------------*/ + +int +compare_occurs (const void *void_first, const void *void_second) +{ +#define first ((OCCURS *) void_first) +#define second ((OCCURS *) void_second) + int value; + + value = compare_words (&first->key, &second->key); + return value == 0 ? first->key.start - second->key.start : value; +#undef first +#undef second +} + +/*------------------------------------------------------------. +| Return !0 if WORD appears in TABLE. Uses a binary search. | +`------------------------------------------------------------*/ + +int +search_table (WORD *word, WORD_TABLE *table) +{ + int lowest; /* current lowest possible index */ + int highest; /* current highest possible index */ + int middle; /* current middle index */ + int value; /* value from last comparison */ + + lowest = 0; + highest = table->length - 1; + while (lowest <= highest) + { + middle = (lowest + highest) / 2; + value = compare_words (word, table->start + middle); + if (value < 0) + highest = middle - 1; + else if (value > 0) + lowest = middle + 1; + else + return 1; + } + return 0; +} + +/*---------------------------------------------------------------------. +| Sort the whole occurs table in memory. Presumably, `qsort' does not | +| take intermediate copies or table elements, so the sort will be | +| stabilized throughout the comparison routine. | +`---------------------------------------------------------------------*/ + +void +sort_found_occurs (void) +{ + + /* Only one language for the time being. */ + + qsort (occurs_table[0], number_of_occurs[0], sizeof (OCCURS), + compare_occurs); +} + +/* Parameter files reading routines. */ + +/*----------------------------------------------------------------------. +| Read a file named FILE_NAME, containing a set of break characters. | +| Build a content to the array word_fastmap in which all characters are | +| allowed except those found in the file. Characters may be repeated. | +`----------------------------------------------------------------------*/ + +void +digest_break_file (const char *file_name) +{ + BLOCK file_contents; /* to receive a copy of the file */ + char *cursor; /* cursor in file copy */ + + swallow_file_in_memory (file_name, &file_contents); + + /* Make the fastmap and record the file contents in it. */ + + memset (word_fastmap, 1, CHAR_SET_SIZE); + for (cursor = file_contents.start; cursor < file_contents.end; cursor++) + word_fastmap[(unsigned char) *cursor] = 0; + + if (!gnu_extensions) + { + + /* If GNU extensions are enabled, the only way to avoid newline as + a break character is to write all the break characters in the + file with no newline at all, not even at the end of the file. + If disabled, spaces, tabs and newlines are always considered as + break characters even if not included in the break file. */ + + word_fastmap[' '] = 0; + word_fastmap['\t'] = 0; + word_fastmap['\n'] = 0; + } + + /* Return the space of the file, which is no more required. */ + + free (file_contents.start); +} + +/*-----------------------------------------------------------------------. +| Read a file named FILE_NAME, containing one word per line, then | +| construct in TABLE a table of WORD descriptors for them. The routine | +| swallows the whole file in memory; this is at the expense of space | +| needed for newlines, which are useless; however, the reading is fast. | +`-----------------------------------------------------------------------*/ + +void +digest_word_file (const char *file_name, WORD_TABLE *table) +{ + BLOCK file_contents; /* to receive a copy of the file */ + char *cursor; /* cursor in file copy */ + char *word_start; /* start of the current word */ + + swallow_file_in_memory (file_name, &file_contents); + + table->start = NULL; + table->length = 0; + + /* Read the whole file. */ + + cursor = file_contents.start; + while (cursor < file_contents.end) + { + + /* Read one line, and save the word in contains. */ + + word_start = cursor; + while (cursor < file_contents.end && *cursor != '\n') + cursor++; + + /* Record the word in table if it is not empty. */ + + if (cursor > word_start) + { + ALLOC_NEW_WORD (table); + table->start[table->length].start = word_start; + table->start[table->length].size = cursor - word_start; + table->length++; + } + + /* This test allows for an incomplete line at end of file. */ + + if (cursor < file_contents.end) + cursor++; + } + + /* Finally, sort all the words read. */ + + qsort (table->start, table->length, (size_t) sizeof (WORD), compare_words); +} + + +/* Keyword recognition and selection. */ + +/*----------------------------------------------------------------------. +| For each keyword in the source text, constructs an OCCURS structure. | +`----------------------------------------------------------------------*/ + +void +find_occurs_in_text (void) +{ + char *cursor; /* for scanning the source text */ + char *scan; /* for scanning the source text also */ + char *line_start; /* start of the current input line */ + char *line_scan; /* newlines scanned until this point */ + int reference_length; /* length of reference in input mode */ + WORD possible_key; /* possible key, to ease searches */ + OCCURS *occurs_cursor; /* current OCCURS under construction */ + + char *context_start; /* start of left context */ + char *context_end; /* end of right context */ + char *word_start; /* start of word */ + char *word_end; /* end of word */ + char *next_context_start; /* next start of left context */ + + /* reference_length is always used within `if (input_reference)'. + However, GNU C diagnoses that it may be used uninitialized. The + following assignment is merely to shut it up. */ + + reference_length = 0; + + /* Tracking where lines start is helpful for reference processing. In + auto reference mode, this allows counting lines. In input reference + mode, this permits finding the beginning of the references. + + The first line begins with the file, skip immediately this very first + reference in input reference mode, to help further rejection any word + found inside it. Also, unconditionally assigning these variable has + the happy effect of shutting up lint. */ + + line_start = text_buffer.start; + line_scan = line_start; + if (input_reference) + { + SKIP_NON_WHITE (line_scan, text_buffer.end); + reference_length = line_scan - line_start; + SKIP_WHITE (line_scan, text_buffer.end); + } + + /* Process the whole buffer, one line or one sentence at a time. */ + + for (cursor = text_buffer.start; + cursor < text_buffer.end; + cursor = next_context_start) + { + + /* `context_start' gets initialized before the processing of each + line, or once for the whole buffer if no end of line or sentence + sequence separator. */ + + context_start = cursor; + + /* If a end of line or end of sentence sequence is defined and + non-empty, `next_context_start' will be recomputed to be the end of + each line or sentence, before each one is processed. If no such + sequence, then `next_context_start' is set at the end of the whole + buffer, which is then considered to be a single line or sentence. + This test also accounts for the case of an incomplete line or + sentence at the end of the buffer. */ + + if (context_regex_string + && (re_search (context_regex, cursor, text_buffer.end - cursor, + 0, text_buffer.end - cursor, &context_regs) + >= 0)) + next_context_start = cursor + context_regs.end[0]; + + else + next_context_start = text_buffer.end; + + /* Include the separator into the right context, but not any suffix + white space in this separator; this insures it will be seen in + output and will not take more space than necessary. */ + + context_end = next_context_start; + SKIP_WHITE_BACKWARDS (context_end, context_start); + + /* Read and process a single input line or sentence, one word at a + time. */ + + while (1) + { + if (word_regex) + + /* If a word regexp has been compiled, use it to skip at the + beginning of the next word. If there is no such word, exit + the loop. */ + + { + if (re_search (word_regex, cursor, context_end - cursor, + 0, context_end - cursor, &word_regs) + < 0) + break; + word_start = cursor + word_regs.start[0]; + word_end = cursor + word_regs.end[0]; + } + else + + /* Avoid re_search and use the fastmap to skip to the + beginning of the next word. If there is no more word in + the buffer, exit the loop. */ + + { + scan = cursor; + while (scan < context_end + && !word_fastmap[(unsigned char) *scan]) + scan++; + + if (scan == context_end) + break; + + word_start = scan; + + while (scan < context_end + && word_fastmap[(unsigned char) *scan]) + scan++; + + word_end = scan; + } + + /* Skip right to the beginning of the found word. */ + + cursor = word_start; + + /* Skip any zero length word. Just advance a single position, + then go fetch the next word. */ + + if (word_end == word_start) + { + cursor++; + continue; + } + + /* This is a genuine, non empty word, so save it as a possible + key. Then skip over it. Also, maintain the maximum length of + all words read so far. It is mandatory to take the maximum + length of all words in the file, without considering if they + are actually kept or rejected, because backward jumps at output + generation time may fall in *any* word. */ + + possible_key.start = cursor; + possible_key.size = word_end - word_start; + cursor += possible_key.size; + + if (possible_key.size > maximum_word_length) + maximum_word_length = possible_key.size; + + /* In input reference mode, update `line_start' from its previous + value. Count the lines just in case auto reference mode is + also selected. If it happens that the word just matched is + indeed part of a reference; just ignore it. */ + + if (input_reference) + { + while (line_scan < possible_key.start) + if (*line_scan == '\n') + { + total_line_count++; + line_scan++; + line_start = line_scan; + SKIP_NON_WHITE (line_scan, text_buffer.end); + reference_length = line_scan - line_start; + } + else + line_scan++; + if (line_scan > possible_key.start) + continue; + } + + /* Ignore the word if an `Ignore words' table exists and if it is + part of it. Also ignore the word if an `Only words' table and + if it is *not* part of it. + + It is allowed that both tables be used at once, even if this + may look strange for now. Just ignore a word that would appear + in both. If regexps are eventually implemented for these + tables, the Ignore table could then reject words that would + have been previously accepted by the Only table. */ + + if (ignore_file && search_table (&possible_key, &ignore_table)) + continue; + if (only_file && !search_table (&possible_key, &only_table)) + continue; + + /* A non-empty word has been found. First of all, insure + proper allocation of the next OCCURS, and make a pointer to + where it will be constructed. */ + + ALLOC_NEW_OCCURS (0); + occurs_cursor = occurs_table[0] + number_of_occurs[0]; + + /* Define the refence field, if any. */ + + if (auto_reference) + { + + /* While auto referencing, update `line_start' from its + previous value, counting lines as we go. If input + referencing at the same time, `line_start' has been + advanced earlier, and the following loop is never really + executed. */ + + while (line_scan < possible_key.start) + if (*line_scan == '\n') + { + total_line_count++; + line_scan++; + line_start = line_scan; + SKIP_NON_WHITE (line_scan, text_buffer.end); + } + else + line_scan++; + + occurs_cursor->reference = total_line_count; + } + else if (input_reference) + { + + /* If only input referencing, `line_start' has been computed + earlier to detect the case the word matched would be part + of the reference. The reference position is simply the + value of `line_start'. */ + + occurs_cursor->reference + = (DELTA) (line_start - possible_key.start); + if (reference_length > reference_max_width) + reference_max_width = reference_length; + } + + /* Exclude the reference from the context in simple cases. */ + + if (input_reference && line_start == context_start) + { + SKIP_NON_WHITE (context_start, context_end); + SKIP_WHITE (context_start, context_end); + } + + /* Completes the OCCURS structure. */ + + occurs_cursor->key = possible_key; + occurs_cursor->left = context_start - possible_key.start; + occurs_cursor->right = context_end - possible_key.start; + + number_of_occurs[0]++; + } + } +} + +/* Formatting and actual output - service routines. */ + +/*-----------------------------------------. +| Prints some NUMBER of spaces on stdout. | +`-----------------------------------------*/ + +void +print_spaces (int number) +{ + int counter; + + for (counter = number; counter > 0; counter--) + putchar (' '); +} + +/*-------------------------------------. +| Prints the field provided by FIELD. | +`-------------------------------------*/ + +void +print_field (BLOCK field) +{ + char *cursor; /* Cursor in field to print */ + int character; /* Current character */ + int base; /* Base character, without diacritic */ + int diacritic; /* Diacritic code for the character */ + + /* Whitespace is not really compressed. Instead, each white space + character (tab, vt, ht etc.) is printed as one single space. */ + + for (cursor = field.start; cursor < field.end; cursor++) + { + character = (unsigned char) *cursor; + if (edited_flag[character]) + { + + /* First check if this is a diacriticized character. + + This works only for TeX. I do not know how diacriticized + letters work with `roff'. Please someone explain it to me! */ + + diacritic = todiac (character); + if (diacritic != 0 && output_format == TEX_FORMAT) + { + base = tobase (character); + switch (diacritic) + { + + case 1: /* Latin diphthongs */ + switch (base) + { + case 'o': + printf ("\\oe{}"); + break; + + case 'O': + printf ("\\OE{}"); + break; + + case 'a': + printf ("\\ae{}"); + break; + + case 'A': + printf ("\\AE{}"); + break; + + default: + putchar (' '); + } + break; + + case 2: /* Acute accent */ + printf ("\\'%s%c", (base == 'i' ? "\\" : ""), base); + break; + + case 3: /* Grave accent */ + printf ("\\`%s%c", (base == 'i' ? "\\" : ""), base); + break; + + case 4: /* Circumflex accent */ + printf ("\\^%s%c", (base == 'i' ? "\\" : ""), base); + break; + + case 5: /* Diaeresis */ + printf ("\\\"%s%c", (base == 'i' ? "\\" : ""), base); + break; + + case 6: /* Tilde accent */ + printf ("\\~%s%c", (base == 'i' ? "\\" : ""), base); + break; + + case 7: /* Cedilla */ + printf ("\\c{%c}", base); + break; + + case 8: /* Small circle beneath */ + switch (base) + { + case 'a': + printf ("\\aa{}"); + break; + + case 'A': + printf ("\\AA{}"); + break; + + default: + putchar (' '); + } + break; + + case 9: /* Strike through */ + switch (base) + { + case 'o': + printf ("\\o{}"); + break; + + case 'O': + printf ("\\O{}"); + break; + + default: + putchar (' '); + } + break; + } + } + else + + /* This is not a diacritic character, so handle cases which are + really specific to `roff' or TeX. All white space processing + is done as the default case of this switch. */ + + switch (character) + { + case '"': + /* In roff output format, double any quote. */ + putchar ('"'); + putchar ('"'); + break; + + case '$': + case '%': + case '&': + case '#': + case '_': + /* In TeX output format, precede these with a backslash. */ + putchar ('\\'); + putchar (character); + break; + + case '{': + case '}': + /* In TeX output format, precede these with a backslash and + force mathematical mode. */ + printf ("$\\%c$", character); + break; + + case '\\': + /* In TeX output mode, request production of a backslash. */ + printf ("\\backslash{}"); + break; + + default: + /* Any other flagged character produces a single space. */ + putchar (' '); + } + } + else + putchar (*cursor); + } +} + + +/* Formatting and actual output - planning routines. */ + +/*--------------------------------------------------------------------. +| From information collected from command line options and input file | +| readings, compute and fix some output parameter values. | +`--------------------------------------------------------------------*/ + +void +fix_output_parameters (void) +{ + int file_index; /* index in text input file arrays */ + int line_ordinal; /* line ordinal value for reference */ + char ordinal_string[12]; /* edited line ordinal for reference */ + int reference_width; /* width for the whole reference */ + int character; /* character ordinal */ + const char *cursor; /* cursor in some constant strings */ + + /* In auto reference mode, the maximum width of this field is + precomputed and subtracted from the overall line width. Add one for + the column which separate the file name from the line number. */ + + if (auto_reference) + { + reference_max_width = 0; + for (file_index = 0; file_index < number_input_files; file_index++) + { + line_ordinal = file_line_count[file_index] + 1; + if (file_index > 0) + line_ordinal -= file_line_count[file_index - 1]; + sprintf (ordinal_string, "%d", line_ordinal); + reference_width = strlen (ordinal_string); + if (input_file_name[file_index]) + reference_width += strlen (input_file_name[file_index]); + if (reference_width > reference_max_width) + reference_max_width = reference_width; + } + reference_max_width++; + reference.start = (char *) xmalloc (reference_max_width + 1); + } + + /* If the reference appears to the left of the output line, reserve some + space for it right away, including one gap size. */ + + if ((auto_reference || input_reference) && !right_reference) + line_width -= reference_max_width + gap_size; + + /* The output lines, minimally, will contain from left to right a left + context, a gap, and a keyword followed by the right context with no + special intervening gap. Half of the line width is dedicated to the + left context and the gap, the other half is dedicated to the keyword + and the right context; these values are computed once and for all here. + There also are tail and head wrap around fields, used when the keyword + is near the beginning or the end of the line, or when some long word + cannot fit in, but leave place from wrapped around shorter words. The + maximum width of these fields are recomputed separately for each line, + on a case by case basis. It is worth noting that it cannot happen that + both the tail and head fields are used at once. */ + + half_line_width = line_width / 2; + before_max_width = half_line_width - gap_size; + keyafter_max_width = half_line_width; + + /* If truncation_string is the empty string, make it NULL to speed up + tests. In this case, truncation_string_length will never get used, so + there is no need to set it. */ + + if (truncation_string && *truncation_string) + truncation_string_length = strlen (truncation_string); + else + truncation_string = NULL; + + if (gnu_extensions) + { + + /* When flagging truncation at the left of the keyword, the + truncation mark goes at the beginning of the before field, + unless there is a head field, in which case the mark goes at the + left of the head field. When flagging truncation at the right + of the keyword, the mark goes at the end of the keyafter field, + unless there is a tail field, in which case the mark goes at the + end of the tail field. Only eight combination cases could arise + for truncation marks: + + . None. + . One beginning the before field. + . One beginning the head field. + . One ending the keyafter field. + . One ending the tail field. + . One beginning the before field, another ending the keyafter field. + . One ending the tail field, another beginning the before field. + . One ending the keyafter field, another beginning the head field. + + So, there is at most two truncation marks, which could appear both + on the left side of the center of the output line, both on the + right side, or one on either side. */ + + before_max_width -= 2 * truncation_string_length; + keyafter_max_width -= 2 * truncation_string_length; + } + else + { + + /* I never figured out exactly how UNIX' ptx plans the output width + of its various fields. If GNU extensions are disabled, do not + try computing the field widths correctly; instead, use the + following formula, which does not completely imitate UNIX' ptx, + but almost. */ + + keyafter_max_width -= 2 * truncation_string_length + 1; + } + + /* Compute which characters need special output processing. Initialize + by flagging any white space character. Some systems do not consider + form feed as a space character, but we do. */ + + for (character = 0; character < CHAR_SET_SIZE; character++) + edited_flag[character] = isspace (character); + edited_flag['\f'] = 1; + + /* Complete the special character flagging according to selected output + format. */ + + switch (output_format) + { + case UNKNOWN_FORMAT: + /* Should never happen. */ + + case DUMB_FORMAT: + break; + + case ROFF_FORMAT: + + /* `Quote' characters should be doubled. */ + + edited_flag['"'] = 1; + break; + + case TEX_FORMAT: + + /* Various characters need special processing. */ + + for (cursor = "$%&#_{}\\"; *cursor; cursor++) + edited_flag[*cursor] = 1; + + /* Any character with 8th bit set will print to a single space, unless + it is diacriticized. */ + + for (character = 0200; character < CHAR_SET_SIZE; character++) + edited_flag[character] = todiac (character) != 0; + break; + } +} + +/*------------------------------------------------------------------. +| Compute the position and length of all the output fields, given a | +| pointer to some OCCURS. | +`------------------------------------------------------------------*/ + +void +define_all_fields (OCCURS *occurs) +{ + int tail_max_width; /* allowable width of tail field */ + int head_max_width; /* allowable width of head field */ + char *cursor; /* running cursor in source text */ + char *left_context_start; /* start of left context */ + char *right_context_end; /* end of right context */ + char *left_field_start; /* conservative start for `head'/`before' */ + int file_index; /* index in text input file arrays */ + const char *file_name; /* file name for reference */ + int line_ordinal; /* line ordinal for reference */ + + /* Define `keyafter', start of left context and end of right context. + `keyafter' starts at the saved position for keyword and extend to the + right from the end of the keyword, eating separators or full words, but + not beyond maximum allowed width for `keyafter' field or limit for the + right context. Suffix spaces will be removed afterwards. */ + + keyafter.start = occurs->key.start; + keyafter.end = keyafter.start + occurs->key.size; + left_context_start = keyafter.start + occurs->left; + right_context_end = keyafter.start + occurs->right; + + cursor = keyafter.end; + while (cursor < right_context_end + && cursor <= keyafter.start + keyafter_max_width) + { + keyafter.end = cursor; + SKIP_SOMETHING (cursor, right_context_end); + } + if (cursor <= keyafter.start + keyafter_max_width) + keyafter.end = cursor; + + keyafter_truncation = truncation_string && keyafter.end < right_context_end; + + SKIP_WHITE_BACKWARDS (keyafter.end, keyafter.start); + + /* When the left context is wide, it might take some time to catch up from + the left context boundary to the beginning of the `head' or `before' + fields. So, in this case, to speed the catchup, we jump back from the + keyword, using some secure distance, possibly falling in the middle of + a word. A secure backward jump would be at least half the maximum + width of a line, plus the size of the longest word met in the whole + input. We conclude this backward jump by a skip forward of at least + one word. In this manner, we should not inadvertently accept only part + of a word. From the reached point, when it will be time to fix the + beginning of `head' or `before' fields, we will skip forward words or + delimiters until we get sufficiently near. */ + + if (-occurs->left > half_line_width + maximum_word_length) + { + left_field_start + = keyafter.start - (half_line_width + maximum_word_length); + SKIP_SOMETHING (left_field_start, keyafter.start); + } + else + left_field_start = keyafter.start + occurs->left; + + /* `before' certainly ends at the keyword, but not including separating + spaces. It starts after than the saved value for the left context, by + advancing it until it falls inside the maximum allowed width for the + before field. There will be no prefix spaces either. `before' only + advances by skipping single separators or whole words. */ + + before.start = left_field_start; + before.end = keyafter.start; + SKIP_WHITE_BACKWARDS (before.end, before.start); + + while (before.start + before_max_width < before.end) + SKIP_SOMETHING (before.start, before.end); + + if (truncation_string) + { + cursor = before.start; + SKIP_WHITE_BACKWARDS (cursor, text_buffer.start); + before_truncation = cursor > left_context_start; + } + else + before_truncation = 0; + + SKIP_WHITE (before.start, text_buffer.end); + + /* The tail could not take more columns than what has been left in the + left context field, and a gap is mandatory. It starts after the + right context, and does not contain prefixed spaces. It ends at + the end of line, the end of buffer or when the tail field is full, + whichever comes first. It cannot contain only part of a word, and + has no suffixed spaces. */ + + tail_max_width + = before_max_width - (before.end - before.start) - gap_size; + + if (tail_max_width > 0) + { + tail.start = keyafter.end; + SKIP_WHITE (tail.start, text_buffer.end); + + tail.end = tail.start; + cursor = tail.end; + while (cursor < right_context_end + && cursor < tail.start + tail_max_width) + { + tail.end = cursor; + SKIP_SOMETHING (cursor, right_context_end); + } + + if (cursor < tail.start + tail_max_width) + tail.end = cursor; + + if (tail.end > tail.start) + { + keyafter_truncation = 0; + tail_truncation = truncation_string && tail.end < right_context_end; + } + else + tail_truncation = 0; + + SKIP_WHITE_BACKWARDS (tail.end, tail.start); + } + else + { + + /* No place left for a tail field. */ + + tail.start = NULL; + tail.end = NULL; + tail_truncation = 0; + } + + /* `head' could not take more columns than what has been left in the right + context field, and a gap is mandatory. It ends before the left + context, and does not contain suffixed spaces. Its pointer is advanced + until the head field has shrunk to its allowed width. It cannot + contain only part of a word, and has no suffixed spaces. */ + + head_max_width + = keyafter_max_width - (keyafter.end - keyafter.start) - gap_size; + + if (head_max_width > 0) + { + head.end = before.start; + SKIP_WHITE_BACKWARDS (head.end, text_buffer.start); + + head.start = left_field_start; + while (head.start + head_max_width < head.end) + SKIP_SOMETHING (head.start, head.end); + + if (head.end > head.start) + { + before_truncation = 0; + head_truncation = (truncation_string + && head.start > left_context_start); + } + else + head_truncation = 0; + + SKIP_WHITE (head.start, head.end); + } + else + { + + /* No place left for a head field. */ + + head.start = NULL; + head.end = NULL; + head_truncation = 0; + } + + if (auto_reference) + { + + /* Construct the reference text in preallocated space from the file + name and the line number. Find out in which file the reference + occurred. Standard input yields an empty file name. Insure line + numbers are one based, even if they are computed zero based. */ + + file_index = 0; + while (file_line_count[file_index] < occurs->reference) + file_index++; + + file_name = input_file_name[file_index]; + if (!file_name) + file_name = ""; + + line_ordinal = occurs->reference + 1; + if (file_index > 0) + line_ordinal -= file_line_count[file_index - 1]; + + sprintf (reference.start, "%s:%d", file_name, line_ordinal); + reference.end = reference.start + strlen (reference.start); + } + else if (input_reference) + { + + /* Reference starts at saved position for reference and extends right + until some white space is met. */ + + reference.start = keyafter.start + (DELTA) occurs->reference; + reference.end = reference.start; + SKIP_NON_WHITE (reference.end, right_context_end); + } +} + + +/* Formatting and actual output - control routines. */ + +/*----------------------------------------------------------------------. +| Output the current output fields as one line for `troff' or `nroff'. | +`----------------------------------------------------------------------*/ + +void +output_one_roff_line (void) +{ + /* Output the `tail' field. */ + + printf (".%s \"", macro_name); + print_field (tail); + if (tail_truncation) + printf ("%s", truncation_string); + putchar ('"'); + + /* Output the `before' field. */ + + printf (" \""); + if (before_truncation) + printf ("%s", truncation_string); + print_field (before); + putchar ('"'); + + /* Output the `keyafter' field. */ + + printf (" \""); + print_field (keyafter); + if (keyafter_truncation) + printf ("%s", truncation_string); + putchar ('"'); + + /* Output the `head' field. */ + + printf (" \""); + if (head_truncation) + printf ("%s", truncation_string); + print_field (head); + putchar ('"'); + + /* Conditionally output the `reference' field. */ + + if (auto_reference || input_reference) + { + printf (" \""); + print_field (reference); + putchar ('"'); + } + + putchar ('\n'); +} + +/*---------------------------------------------------------. +| Output the current output fields as one line for `TeX'. | +`---------------------------------------------------------*/ + +void +output_one_tex_line (void) +{ + BLOCK key; /* key field, isolated */ + BLOCK after; /* after field, isolated */ + char *cursor; /* running cursor in source text */ + + printf ("\\%s ", macro_name); + printf ("{"); + print_field (tail); + printf ("}{"); + print_field (before); + printf ("}{"); + key.start = keyafter.start; + after.end = keyafter.end; + cursor = keyafter.start; + SKIP_SOMETHING (cursor, keyafter.end); + key.end = cursor; + after.start = cursor; + print_field (key); + printf ("}{"); + print_field (after); + printf ("}{"); + print_field (head); + printf ("}"); + if (auto_reference || input_reference) + { + printf ("{"); + print_field (reference); + printf ("}"); + } + printf ("\n"); +} + +/*-------------------------------------------------------------------. +| Output the current output fields as one line for a dumb terminal. | +`-------------------------------------------------------------------*/ + +void +output_one_dumb_line (void) +{ + if (!right_reference) + if (auto_reference) + { + + /* Output the `reference' field, in such a way that GNU emacs + next-error will handle it. The ending colon is taken from the + gap which follows. */ + + print_field (reference); + putchar (':'); + print_spaces (reference_max_width + + gap_size + - (reference.end - reference.start) + - 1); + } + else + { + + /* Output the `reference' field and its following gap. */ + + print_field (reference); + print_spaces (reference_max_width + + gap_size + - (reference.end - reference.start)); + } + + if (tail.start < tail.end) + { + /* Output the `tail' field. */ + + print_field (tail); + if (tail_truncation) + printf ("%s", truncation_string); + + print_spaces (half_line_width - gap_size + - (before.end - before.start) + - (before_truncation ? truncation_string_length : 0) + - (tail.end - tail.start) + - (tail_truncation ? truncation_string_length : 0)); + } + else + print_spaces (half_line_width - gap_size + - (before.end - before.start) + - (before_truncation ? truncation_string_length : 0)); + + /* Output the `before' field. */ + + if (before_truncation) + printf ("%s", truncation_string); + print_field (before); + + print_spaces (gap_size); + + /* Output the `keyafter' field. */ + + print_field (keyafter); + if (keyafter_truncation) + printf ("%s", truncation_string); + + if (head.start < head.end) + { + /* Output the `head' field. */ + + print_spaces (half_line_width + - (keyafter.end - keyafter.start) + - (keyafter_truncation ? truncation_string_length : 0) + - (head.end - head.start) + - (head_truncation ? truncation_string_length : 0)); + if (head_truncation) + printf ("%s", truncation_string); + print_field (head); + } + else + + if ((auto_reference || input_reference) && right_reference) + print_spaces (half_line_width + - (keyafter.end - keyafter.start) + - (keyafter_truncation ? truncation_string_length : 0)); + + if ((auto_reference || input_reference) && right_reference) + { + /* Output the `reference' field. */ + + print_spaces (gap_size); + print_field (reference); + } + + printf ("\n"); +} + +/*------------------------------------------------------------------------. +| Scan the whole occurs table and, for each entry, output one line in the | +| appropriate format. | +`------------------------------------------------------------------------*/ + +void +generate_all_output (void) +{ + int occurs_index; /* index of keyword entry being processed */ + OCCURS *occurs_cursor; /* current keyword entry being processed */ + + + /* The following assignments are useful to provide default values in case + line contexts or references are not used, in which case these variables + would never be computed. */ + + tail.start = NULL; + tail.end = NULL; + tail_truncation = 0; + + head.start = NULL; + head.end = NULL; + head_truncation = 0; + + + /* Loop over all keyword occurrences. */ + + occurs_cursor = occurs_table[0]; + + for (occurs_index = 0; occurs_index < number_of_occurs[0]; occurs_index++) + { + /* Compute the exact size of every field and whenever truncation flags + are present or not. */ + + define_all_fields (occurs_cursor); + + /* Produce one output line according to selected format. */ + + switch (output_format) + { + case UNKNOWN_FORMAT: + /* Should never happen. */ + + case DUMB_FORMAT: + output_one_dumb_line (); + break; + + case ROFF_FORMAT: + output_one_roff_line (); + break; + + case TEX_FORMAT: + output_one_tex_line (); + break; + } + + /* Advance the cursor into the occurs table. */ + + occurs_cursor++; + } +} + +/* Option decoding and main program. */ + +/*------------------------------------------------------. +| Print program identification and options, then exit. | +`------------------------------------------------------*/ + +void +usage (int status) +{ + if (status != 0) + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + else + { + printf ("\ +Usage: %s [OPTION]... [INPUT]... (without -G)\n\ + or: %s -G [OPTION]... [INPUT [OUTPUT]]\n", program_name, program_name); + printf ("\ +\n\ + -A, --auto-reference output automatically generated references\n\ + -C, --copyright display Copyright and copying conditions\n\ + -G, --traditional behave more like System V `ptx'\n\ + -F, --flag-truncation=STRING use STRING for flagging line truncations\n\ + -M, --macro-name=STRING macro name to use instead of `xx'\n\ + -O, --format=roff generate output as roff directives\n\ + -R, --right-side-refs put references at right, not counted in -w\n\ + -S, --sentence-regexp=REGEXP for end of lines or end of sentences\n\ + -T, --format=tex generate output as TeX directives\n\ + -W, --word-regexp=REGEXP use REGEXP to match each keyword\n\ + -b, --break-file=FILE word break characters in this FILE\n\ + -f, --ignore-case fold lower case to upper case for sorting\n\ + -g, --gap-size=NUMBER gap size in columns between output fields\n\ + -i, --ignore-file=FILE read ignore word list from FILE\n\ + -o, --only-file=FILE read only word list from this FILE\n\ + -r, --references first field of each line is a reference\n\ + -t, --typeset-mode - not implemented -\n\ + -w, --width=NUMBER output width in columns, reference excluded\n\ + --help display this help and exit\n\ + --version output version information and exit\n\ +\n\ +With no FILE or if FILE is -, read Standard Input. `-F /' by default.\n"); + } + exit (status); +} + +/*----------------------------------------------------------------------. +| Main program. Decode ARGC arguments passed through the ARGV array of | +| strings, then launch execution. | +`----------------------------------------------------------------------*/ + +/* Long options equivalences. */ +const struct option long_options[] = +{ + {"auto-reference", no_argument, NULL, 'A'}, + {"break-file", required_argument, NULL, 'b'}, + {"copyright", no_argument, NULL, 'C'}, + {"flag-truncation", required_argument, NULL, 'F'}, + {"ignore-case", no_argument, NULL, 'f'}, + {"gap-size", required_argument, NULL, 'g'}, + {"help", no_argument, &show_help, 1}, + {"ignore-file", required_argument, NULL, 'i'}, + {"macro-name", required_argument, NULL, 'M'}, + {"only-file", required_argument, NULL, 'o'}, + {"references", no_argument, NULL, 'r'}, + {"right-side-refs", no_argument, NULL, 'R'}, + {"format", required_argument, NULL, 10}, + {"sentence-regexp", required_argument, NULL, 'S'}, + {"traditional", no_argument, NULL, 'G'}, + {"typeset-mode", no_argument, NULL, 't'}, + {"version", no_argument, &show_version, 1}, + {"width", required_argument, NULL, 'w'}, + {"word-regexp", required_argument, NULL, 'W'}, + {0, 0, 0, 0}, +}; + +static char const* const format_args[] = +{ + "roff", "tex", 0 +}; + +int +main (int argc, char *const argv[]) +{ + int optchar; /* argument character */ + extern int optind; /* index of argument */ + extern char *optarg; /* value or argument */ + int file_index; /* index in text input file arrays */ + +#ifdef HAVE_MCHECK + /* Use GNU malloc checking. It has proven to be useful! */ + mcheck (); +#endif /* HAVE_MCHECK */ + +#ifdef STDC_HEADERS +#ifdef HAVE_SETCHRCLASS + setchrclass (NULL); +#endif +#endif + + /* Decode program options. */ + + program_name = argv[0]; + + while ((optchar = getopt_long (argc, argv, "ACF:GM:ORS:TW:b:i:fg:o:trw:", + long_options, NULL)), + optchar != EOF) + { + switch (optchar) + { + default: + usage (1); + + case 0: + break; + + case 'C': + printf ("%s", copyright); + exit (0); + + case 'G': + gnu_extensions = 0; + break; + + case 'b': + break_file = optarg; + break; + + case 'f': + ignore_case = 1; + break; + + case 'g': + gap_size = atoi (optarg); + break; + + case 'i': + ignore_file = optarg; + break; + + case 'o': + only_file = optarg; + break; + + case 'r': + input_reference = 1; + break; + + case 't': + /* A decouvrir... */ + break; + + case 'w': + line_width = atoi (optarg); + break; + + case 'A': + auto_reference = 1; + break; + + case 'F': + truncation_string = copy_unescaped_string (optarg); + break; + + case 'M': + macro_name = optarg; + break; + + case 'O': + output_format = ROFF_FORMAT; + break; + + case 'R': + right_reference = 1; + break; + + case 'S': + context_regex_string = copy_unescaped_string (optarg); + break; + + case 'T': + output_format = TEX_FORMAT; + break; + + case 'W': + word_regex_string = copy_unescaped_string (optarg); + break; + + case 10: + switch (argmatch (optarg, format_args)) + { + default: + usage (1); + + case 0: + output_format = ROFF_FORMAT; + break; + + case 1: + output_format = TEX_FORMAT; + break; + } + } + } + + /* Process trivial options. */ + + if (show_help) + usage (0); + + if (show_version) + { + printf ("%s\n", version_string); + exit (0); + } + + /* Change the default Ignore file if one is defined. */ + +#ifdef DEFAULT_IGNORE_FILE + if (!ignore_file) + ignore_file = DEFAULT_IGNORE_FILE; +#endif + + /* Process remaining arguments. If GNU extensions are enabled, process + all arguments as input parameters. If disabled, accept at most two + arguments, the second of which is an output parameter. */ + + if (optind == argc) + { + + /* No more argument simply means: read standard input. */ + + input_file_name = (const char **) xmalloc (sizeof (const char *)); + file_line_count = (int *) xmalloc (sizeof (int)); + number_input_files = 1; + input_file_name[0] = NULL; + } + else if (gnu_extensions) + { + number_input_files = argc - optind; + input_file_name + = (const char **) xmalloc (number_input_files * sizeof (const char *)); + file_line_count + = (int *) xmalloc (number_input_files * sizeof (int)); + + for (file_index = 0; file_index < number_input_files; file_index++) + { + input_file_name[file_index] = argv[optind]; + if (!*argv[optind] || strcmp (argv[optind], "-") == 0) + input_file_name[0] = NULL; + else + input_file_name[0] = argv[optind]; + optind++; + } + } + else + { + + /* There is one necessary input file. */ + + number_input_files = 1; + input_file_name = (const char **) xmalloc (sizeof (const char *)); + file_line_count = (int *) xmalloc (sizeof (int)); + if (!*argv[optind] || strcmp (argv[optind], "-") == 0) + input_file_name[0] = NULL; + else + input_file_name[0] = argv[optind]; + optind++; + + /* Redirect standard output, only if requested. */ + + if (optind < argc) + { + fclose (stdout); + if (fopen (argv[optind], "w") == NULL) + error (1, errno, argv[optind]); + optind++; + } + + /* Diagnose any other argument as an error. */ + + if (optind < argc) + usage (1); + } + + /* If the output format has not been explicitly selected, choose dumb + terminal format if GNU extensions are enabled, else `roff' format. */ + + if (output_format == UNKNOWN_FORMAT) + output_format = gnu_extensions ? DUMB_FORMAT : ROFF_FORMAT; + + /* Initialize the main tables. */ + + initialize_regex (); + + /* Read `Break character' file, if any. */ + + if (break_file) + digest_break_file (break_file); + + /* Read `Ignore words' file and `Only words' files, if any. If any of + these files is empty, reset the name of the file to NULL, to avoid + unnecessary calls to search_table. */ + + if (ignore_file) + { + digest_word_file (ignore_file, &ignore_table); + if (ignore_table.length == 0) + ignore_file = NULL; + } + + if (only_file) + { + digest_word_file (only_file, &only_table); + if (only_table.length == 0) + only_file = NULL; + } + + /* Prepare to study all the input files. */ + + number_of_occurs[0] = 0; + total_line_count = 0; + maximum_word_length = 0; + reference_max_width = 0; + + for (file_index = 0; file_index < number_input_files; file_index++) + { + + /* Read the file in core, than study it. */ + + swallow_file_in_memory (input_file_name[file_index], &text_buffer); + find_occurs_in_text (); + + /* Maintain for each file how many lines has been read so far when its + end is reached. Incrementing the count first is a simple kludge to + handle a possible incomplete line at end of file. */ + + total_line_count++; + file_line_count[file_index] = total_line_count; + } + + /* Do the output process phase. */ + + sort_found_occurs (); + fix_output_parameters (); + generate_all_output (); + + /* All done. */ + + exit (0); +} diff --git a/gnu/usr.bin/ptx/ptx.info b/gnu/usr.bin/ptx/ptx.info new file mode 100644 index 000000000000..3bbd1bb8cf07 --- /dev/null +++ b/gnu/usr.bin/ptx/ptx.info @@ -0,0 +1,496 @@ +This is Info file ptx.info, produced by Makeinfo-1.47 from the input +file ./ptx.texinfo. + + This file documents the `ptx' command, which has the purpose of +generated permuted indices for group of files. + + Copyright (C) 1990, 1991, 1993 by the Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual 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. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: ptx.info, Node: Top, Next: Invoking ptx, Prev: (dir), Up: (dir) + +Introduction +************ + + This is the 0.3 beta release of `ptx', the GNU version of a permuted +index generator. This software has the main goal of providing a +replacement for the traditional `ptx' as found on System V machines, +able to handle small files quickly, while providing a platform for more +development. + + This version reimplements and extends traditional `ptx'. Among +other things, it can produce a readable "KWIC" (keywords in their +context) without the need of `nroff', there is also an option to +produce TeX compatible output. This version does not handle huge input +files, that is, those files which do not fit in memory all at once. + + *Please note* that an overall renaming of all options is +foreseeable. In fact, GNU ptx specifications are not frozen yet. + +* Menu: + +* Invoking ptx:: How to use this program +* Compatibility:: The GNU extensions to `ptx' + + -- The Detailed Node Listing -- + +How to use this program + +* General options:: Options which affect general program behaviour. +* Charset selection:: Underlying character set considerations. +* Input processing:: Input fields, contexts, and keyword selection. +* Output formatting:: Types of output format, and sizing the fields. + + +File: ptx.info, Node: Invoking ptx, Next: Compatibility, Prev: Top, Up: Top + +How to use this program +*********************** + + This tool reads a text file and essentially produces a permuted +index, with each keyword in its context. The calling sketch is one of: + + ptx [OPTION ...] [FILE ...] + + or: + + ptx -G [OPTION ...] [INPUT [OUTPUT]] + + The `-G' (or its equivalent: `--traditional') option disables all +GNU extensions and revert to traditional mode, thus introducing some +limitations, and changes several of the program's default option values. +When `-G' is not specified, GNU extensions are always enabled. GNU +extensions to `ptx' are documented wherever appropriate in this +document. See *Note Compatibility:: for an explicit list of them. + + Individual options are explained later in this document. + + When GNU extensions are enabled, there may be zero, one or several +FILE after the options. If there is no FILE, the program reads the +standard input. If there is one or several FILE, they give the name of +input files which are all read in turn, as if all the input files were +concatenated. However, there is a full contextual break between each +file and, when automatic referencing is requested, file names and line +numbers refer to individual text input files. In all cases, the +program produces the permuted index onto the standard output. + + When GNU extensions are *not* enabled, that is, when the program +operates in traditional mode, there may be zero, one or two parameters +besides the options. If there is no parameters, the program reads the +standard input and produces the permuted index onto the standard output. +If there is only one parameter, it names the text INPUT to be read +instead of the standard input. If two parameters are given, they give +respectively the name of the INPUT file to read and the name of the +OUTPUT file to produce. *Be very careful* to note that, in this case, +the contents of file given by the second parameter is destroyed. This +behaviour is dictated only by System V `ptx' compatibility, because GNU +Standards discourage output parameters not introduced by an option. + + Note that for *any* file named as the value of an option or as an +input text file, a single dash `-' may be used, in which case standard +input is assumed. However, it would not make sense to use this +convention more than once per program invocation. + +* Menu: + +* General options:: Options which affect general program behaviour. +* Charset selection:: Underlying character set considerations. +* Input processing:: Input fields, contexts, and keyword selection. +* Output formatting:: Types of output format, and sizing the fields. + + +File: ptx.info, Node: General options, Next: Charset selection, Prev: Invoking ptx, Up: Invoking ptx + +General options +=============== + +`-C' +`--copyright' + Prints a short note about the Copyright and copying conditions, + then exit without further processing. + +`-G' +`--traditional' + As already explained, this option disables all GNU extensions to + `ptx' and switch to traditional mode. + +`--help' + Prints a short help on standard output, then exit without further + processing. + +`--version' + Prints the program verison on standard output, then exit without + further processing. + + +File: ptx.info, Node: Charset selection, Next: Input processing, Prev: General options, Up: Invoking ptx + +Charset selection +================= + + As it is setup now, the program assumes that the input file is coded +using 8-bit ISO 8859-1 code, also known as Latin-1 character set, +*unless* if it is compiled for MS-DOS, in which case it uses the +character set of the IBM-PC. (GNU `ptx' is not known to work on +smaller MS-DOS machines anymore.) Compared to 7-bit ASCII, the set of +characters which are letters is then different, this fact alters the +behaviour of regular expression matching. Thus, the default regular +expression for a keyword allows foreign or diacriticized letters. +Keyword sorting, however, is still crude; it obeys the underlying +character set ordering quite blindly. + +`-f' +`--ignore-case' + Fold lower case letters to upper case for sorting. + + +File: ptx.info, Node: Input processing, Next: Output formatting, Prev: Charset selection, Up: Invoking ptx + +Word selection +============== + +`-b FILE' +`--break-file=FILE' + This option is an alternative way to option `-W' for describing + which characters make up words. This option introduces the name + of a file which contains a list of characters which can*not* be + part of one word, this file is called the "Break file". Any + character which is not part of the Break file is a word + constituent. If both options `-b' and `-W' are specified, then + `-W' has precedence and `-b' is ignored. + + When GNU extensions are enabled, the only way to avoid newline as a + break character is to write all the break characters in the file + with no newline at all, not even at the end of the file. When GNU + extensions are disabled, spaces, tabs and newlines are always + considered as break characters even if not included in the Break + file. + +`-i FILE' +`--ignore-file=FILE' + The file associated with this option contains a list of words + which will never be taken as keywords in concordance output. It + is called the "Ignore file". The file contains exactly one word + in each line; the end of line separation of words is not subject + to the value of the `-S' option. + + There is a default Ignore file used by `ptx' when this option is + not specified, usually found in `/usr/local/lib/eign' if this has + not been changed at installation time. If you want to deactivate + the default Ignore file, specify `/dev/null' instead. + +`-o FILE' +`--only-file=FILE' + The file associated with this option contains a list of words + which will be retained in concordance output, any word not + mentioned in this file is ignored. The file is called the "Only + file". The file contains exactly one word in each line; the end + of line separation of words is not subject to the value of the + `-S' option. + + There is no default for the Only file. In the case there are both + an Only file and an Ignore file, a word will be subject to be a + keyword only if it is given in the Only file and not given in the + Ignore file. + +`-r' +`--references' + On each input line, the leading sequence of non white characters + will be taken to be a reference that has the purpose of + identifying this input line on the produced permuted index. See + *Note Output formatting:: for more information about reference + production. Using this option change the default value for option + `-S'. + + Using this option, the program does not try very hard to remove + references from contexts in output, but it succeeds in doing so + *when* the context ends exactly at the newline. If option `-r' is + used with `-S' default value, or when GNU extensions are disabled, + this condition is always met and references are completely + excluded from the output contexts. + +`-S REGEXP' +`--sentence-regexp=REGEXP' + This option selects which regular expression will describe the end + of a line or the end of a sentence. In fact, there is other + distinction between end of lines or end of sentences than the + effect of this regular expression, and input line boundaries have + no special significance outside this option. By default, when GNU + extensions are enabled and if `-r' option is not used, end of + sentences are used. In this case, the precise REGEX is imported + from GNU emacs: + + [.?!][]\"')}]*\\($\\|\t\\| \\)[ \t\n]* + + Whenever GNU extensions are disabled or if `-r' option is used, end + of lines are used; in this case, the default REGEXP is just: + + \n + + Using an empty REGEXP is equivalent to completely disabling end of + line or end of sentence recognition. In this case, the whole file + is considered to be a single big line or sentence. The user might + want to disallow all truncation flag generation as well, through + option `-F ""'. *Note Syntax of Regular Expressions: + (emacs)Regexps. + + When the keywords happen to be near the beginning of the input + line or sentence, this often creates an unused area at the + beginning of the output context line; when the keywords happen to + be near the end of the input line or sentence, this often creates + an unused area at the end of the output context line. The program + tries to fill those unused areas by wrapping around context in + them; the tail of the input line or sentence is used to fill the + unused area on the left of the output line; the head of the input + line or sentence is used to fill the unused area on the right of + the output line. + + As a matter of convenience to the user, many usual backslashed + escape sequences, as found in the C language, are recognized and + converted to the corresponding characters by `ptx' itself. + +`-W REGEXP' +`--word-regexp=REGEXP' + This option selects which regular expression will describe each + keyword. By default, if GNU extensions are enabled, a word is a + sequence of letters; the REGEXP used is `\w+'. When GNU + extensions are disabled, a word is by default anything which ends + with a space, a tab or a newline; the REGEXP used is `[^ \t\n]+'. + + An empty REGEXP is equivalent to not using this option, letting the + default dive in. *Note Syntax of Regular Expressions: + (emacs)Regexps. + + As a matter of convenience to the user, many usual backslashed + escape sequences, as found in the C language, are recognized and + converted to the corresponding characters by `ptx' itself. + + +File: ptx.info, Node: Output formatting, Prev: Input processing, Up: Invoking ptx + +Output formatting +================= + + Output format is mainly controlled by `-O' and `-T' options, +described in the table below. When neither `-O' nor `-T' is selected, +and if GNU extensions are enabled, the program choose an output format +suited for a dumb terminal. Each keyword occurrence is output to the +center of one line, surrounded by its left and right contexts. Each +field is properly justified, so the concordance output could readily be +observed. As a special feature, if automatic references are selected +by option `-A' and are output before the left context, that is, if +option `-R' is *not* selected, then a colon is added after the +reference; this nicely interfaces with GNU Emacs `next-error' +processing. In this default output format, each white space character, +like newline and tab, is merely changed to exactly one space, with no +special attempt to compress consecutive spaces. This might change in +the future. Except for those white space characters, every other +character of the underlying set of 256 characters is transmitted +verbatim. + + Output format is further controlled by the following options. + +`-g NUMBER' +`--gap-size=NUMBER' + Select the size of the minimum white gap between the fields on the + output line. + +`-w NUMBER' +`--width=NUMBER' + Select the output maximum width of each final line. If references + are used, they are included or excluded from the output maximum + width depending on the value of option `-R'. If this option is not + selected, that is, when references are output before the left + context, the output maximum width takes into account the maximum + length of all references. If this options is selected, that is, + when references are output after the right context, the output + maximum width does not take into account the space taken by + references, nor the gap that precedes them. + +`-A' +`--auto-reference' + Select automatic references. Each input line will have an + automatic reference made up of the file name and the line ordinal, + with a single colon between them. However, the file name will be + empty when standard input is being read. If both `-A' and `-r' + are selected, then the input reference is still read and skipped, + but the automatic reference is used at output time, overriding the + input reference. + +`-R' +`--right-side-refs' + In default output format, when option `-R' is not used, any + reference produced by the effect of options `-r' or `-A' are given + to the far right of output lines, after the right context. In + default output format, when option `-R' is specified, references + are rather given to the beginning of each output line, before the + left context. For any other output format, option `-R' is almost + ignored, except for the fact that the width of references is *not* + taken into account in total output width given by `-w' whenever + `-R' is selected. + + This option is automatically selected whenever GNU extensions are + disabled. + +`-F STRING' +`--flac-truncation=STRING' + This option will request that any truncation in the output be + reported using the string STRING. Most output fields + theoretically extend towards the beginning or the end of the + current line, or current sentence, as selected with option `-S'. + But there is a maximum allowed output line width, changeable + through option `-w', which is further divided into space for + various output fields. When a field has to be truncated because + cannot extend until the beginning or the end of the current line + to fit in the, then a truncation occurs. By default, the string + used is a single slash, as in `-F /'. + + STRING may have more than one character, as in `-F ...'. Also, in + the particular case STRING is empty (`-F ""'), truncation flagging + is disabled, and no truncation marks are appended in this case. + + As a matter of convenience to the user, many usual backslashed + escape sequences, as found in the C language, are recognized and + converted to the corresponding characters by `ptx' itself. + +`-M STRING' +`--macro-name=STRING' + Select another STRING to be used instead of `xx', while generating + output suitable for `nroff', `troff' or TeX. + +`-O' +`--format=roff' + Choose an output format suitable for `nroff' or `troff' + processing. Each output line will look like: + + .xx "TAIL" "BEFORE" "KEYWORD_AND_AFTER" "HEAD" "REF" + + so it will be possible to write an `.xx' roff macro to take care of + the output typesetting. This is the default output format when GNU + extensions are disabled. Option `-M' might be used to change `xx' + to another macro name. + + In this output format, each non-graphical character, like newline + and tab, is merely changed to exactly one space, with no special + attempt to compress consecutive spaces. Each quote character: `"' + is doubled so it will be correctly processed by `nroff' or `troff'. + +`-T' +`--format=tex' + Choose an output format suitable for TeX processing. Each output + line will look like: + + \xx {TAIL}{BEFORE}{KEYWORD}{AFTER}{HEAD}{REF} + + so it will be possible to write write a `\xx' definition to take + care of the output typesetting. Note that when references are not + being produced, that is, neither option `-A' nor option `-r' is + selected, the last parameter of each `\xx' call is inhibited. + Option `-M' might be used to change `xx' to another macro name. + + In this output format, some special characters, like `$', `%', + `&', `#' and `_' are automatically protected with a backslash. + Curly brackets `{', `}' are also protected with a backslash, but + also enclosed in a pair of dollar signs to force mathematical + mode. The backslash itself produces the sequence `\backslash{}'. + Circumflex and tilde diacritics produce the sequence `^\{ }' and + `~\{ }' respectively. Other diacriticized characters of the + underlying character set produce an appropriate TeX sequence as + far as possible. The other non-graphical characters, like newline + and tab, and all others characters which are not part of ASCII, + are merely changed to exactly one space, with no special attempt + to compress consecutive spaces. Let me know how to improve this + special character processing for TeX. + + +File: ptx.info, Node: Compatibility, Prev: Invoking ptx, Up: Top + +The GNU extensions to `ptx' +*************************** + + This version of `ptx' contains a few features which do not exist in +System V `ptx'. These extra features are suppressed by using the `-G' +command line option, unless overridden by other command line options. +Some GNU extensions cannot be recovered by overriding, so the simple +rule is to avoid `-G' if you care about GNU extensions. Here are the +differences between this program and System V `ptx'. + + * This program can read many input files at once, it always writes + the resulting concordance on standard output. On the other end, + System V `ptx' reads only one file and produce the result on + standard output or, if a second FILE parameter is given on the + command, to that FILE. + + Having output parameters not introduced by options is a quite + dangerous practice which GNU avoids as far as possible. So, for + using `ptx' portably between GNU and System V, you should pay + attention to always use it with a single input file, and always + expect the result on standard output. You might also want to + automatically configure in a `-G' option to `ptx' calls in + products using `ptx', if the configurator finds that the installed + `ptx' accepts `-G'. + + * The only options available in System V `ptx' are options `-b', + `-f', `-g', `-i', `-o', `-r', `-t' and `-w'. All other options + are GNU extensions and are not repeated in this enumeration. + Moreover, some options have a slightly different meaning when GNU + extensions are enabled, as explained below. + + * By default, concordance output is not formatted for `troff' or + `nroff'. It is rather formatted for a dumb terminal. `troff' or + `nroff' output may still be selected through option `-O'. + + * Unless `-R' option is used, the maximum reference width is + subtracted from the total output line width. With GNU extensions + disabled, width of references is not taken into account in the + output line width computations. + + * All 256 characters, even `NUL's, are always read and processed from + input file with no adverse effect, even if GNU extensions are + disabled. However, System V `ptx' does not accept 8-bit + characters, a few control characters are rejected, and the tilda + `~' is condemned. + + * Input line length is only limited by available memory, even if GNU + extensions are disabled. However, System V `ptx' processes only + the first 200 characters in each line. + + * The break (non-word) characters default to be every character + except all letters of the underlying character set, diacriticized + or not. When GNU extensions are disabled, the break characters + default to space, tab and newline only. + + * The program makes better use of output line width. If GNU + extensions are disabled, the program rather tries to imitate + System V `ptx', but still, there are some slight disposition + glitches this program does not completely reproduce. + + * The user can specify both an Ignore file and an Only file. This + is not allowed with System V `ptx'. + + + +Tag Table: +Node: Top939 +Node: Invoking ptx2298 +Node: General options5025 +Node: Charset selection5639 +Node: Input processing6514 +Node: Output formatting12205 +Node: Compatibility18737 + +End Tag Table diff --git a/gnu/usr.bin/ptx/ptx.texinfo b/gnu/usr.bin/ptx/ptx.texinfo new file mode 100644 index 000000000000..e690c55f80c1 --- /dev/null +++ b/gnu/usr.bin/ptx/ptx.texinfo @@ -0,0 +1,554 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename ptx.info +@settitle GNU @code{ptx} reference manual +@finalout +@c %**end of header + +@ifinfo +This file documents the @code{ptx} command, which has the purpose of +generated permuted indices for group of files. + +Copyright (C) 1990, 1991, 1993 by the Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual 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. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end ifinfo + +@titlepage +@title ptx +@subtitle The GNU permuted indexer +@subtitle Edition 0.3, for ptx version 0.3 +@subtitle November 1993 +@author by Francois Pinard + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1990, 1991, 1993 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual 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. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage + +@node Top, Invoking ptx, (dir), (dir) +@chapter Introduction + +This is the 0.3 beta release of @code{ptx}, the GNU version of a +permuted index generator. This software has the main goal of providing +a replacement for the traditional @code{ptx} as found on System V +machines, able to handle small files quickly, while providing a platform +for more development. + +This version reimplements and extends traditional @code{ptx}. Among +other things, it can produce a readable @dfn{KWIC} (keywords in their +context) without the need of @code{nroff}, there is also an option to +produce @TeX{} compatible output. This version does not handle huge +input files, that is, those files which do not fit in memory all at +once. + +@emph{Please note} that an overall renaming of all options is +foreseeable. In fact, GNU ptx specifications are not frozen yet. + +@menu +* Invoking ptx:: How to use this program +* Compatibility:: The GNU extensions to @code{ptx} + + --- The Detailed Node Listing --- + +How to use this program + +* General options:: Options which affect general program behaviour. +* Charset selection:: Underlying character set considerations. +* Input processing:: Input fields, contexts, and keyword selection. +* Output formatting:: Types of output format, and sizing the fields. +@end menu + +@node Invoking ptx, Compatibility, Top, Top +@chapter How to use this program + +This tool reads a text file and essentially produces a permuted index, with +each keyword in its context. The calling sketch is one of: + +@example +ptx [@var{option} @dots{}] [@var{file} @dots{}] +@end example + +or: + +@example +ptx -G [@var{option} @dots{}] [@var{input} [@var{output}]] +@end example + +The @samp{-G} (or its equivalent: @samp{--traditional}) option disables +all GNU extensions and revert to traditional mode, thus introducing some +limitations, and changes several of the program's default option values. +When @samp{-G} is not specified, GNU extensions are always enabled. GNU +extensions to @code{ptx} are documented wherever appropriate in this +document. See @xref{Compatibility} for an explicit list of them. + +Individual options are explained later in this document. + +When GNU extensions are enabled, there may be zero, one or several +@var{file} after the options. If there is no @var{file}, the program +reads the standard input. If there is one or several @var{file}, they +give the name of input files which are all read in turn, as if all the +input files were concatenated. However, there is a full contextual +break between each file and, when automatic referencing is requested, +file names and line numbers refer to individual text input files. In +all cases, the program produces the permuted index onto the standard +output. + +When GNU extensions are @emph{not} enabled, that is, when the program +operates in traditional mode, there may be zero, one or two parameters +besides the options. If there is no parameters, the program reads the +standard input and produces the permuted index onto the standard output. +If there is only one parameter, it names the text @var{input} to be read +instead of the standard input. If two parameters are given, they give +respectively the name of the @var{input} file to read and the name of +the @var{output} file to produce. @emph{Be very careful} to note that, +in this case, the contents of file given by the second parameter is +destroyed. This behaviour is dictated only by System V @code{ptx} +compatibility, because GNU Standards discourage output parameters not +introduced by an option. + +Note that for @emph{any} file named as the value of an option or as an +input text file, a single dash @kbd{-} may be used, in which case +standard input is assumed. However, it would not make sense to use this +convention more than once per program invocation. + +@menu +* General options:: Options which affect general program behaviour. +* Charset selection:: Underlying character set considerations. +* Input processing:: Input fields, contexts, and keyword selection. +* Output formatting:: Types of output format, and sizing the fields. +@end menu + +@node General options, Charset selection, Invoking ptx, Invoking ptx +@section General options + +@table @code + +@item -C +@itemx --copyright +Prints a short note about the Copyright and copying conditions, then +exit without further processing. + +@item -G +@itemx --traditional +As already explained, this option disables all GNU extensions to +@code{ptx} and switch to traditional mode. + +@item --help +Prints a short help on standard output, then exit without further +processing. + +@item --version +Prints the program verison on standard output, then exit without further +processing. + +@end table + +@node Charset selection, Input processing, General options, Invoking ptx +@section Charset selection + +As it is setup now, the program assumes that the input file is coded +using 8-bit ISO 8859-1 code, also known as Latin-1 character set, +@emph{unless} if it is compiled for MS-DOS, in which case it uses the +character set of the IBM-PC. (GNU @code{ptx} is not known to work on +smaller MS-DOS machines anymore.) Compared to 7-bit ASCII, the set of +characters which are letters is then different, this fact alters the +behaviour of regular expression matching. Thus, the default regular +expression for a keyword allows foreign or diacriticized letters. +Keyword sorting, however, is still crude; it obeys the underlying +character set ordering quite blindly. + +@table @code + +@item -f +@itemx --ignore-case +Fold lower case letters to upper case for sorting. + +@end table + +@node Input processing, Output formatting, Charset selection, Invoking ptx +@section Word selection + +@table @code + +@item -b @var{file} +@item --break-file=@var{file} + +This option is an alternative way to option @code{-W} for describing +which characters make up words. This option introduces the name of a +file which contains a list of characters which can@emph{not} be part of +one word, this file is called the @dfn{Break file}. Any character which +is not part of the Break file is a word constituent. If both options +@code{-b} and @code{-W} are specified, then @code{-W} has precedence and +@code{-b} is ignored. + +When GNU extensions are enabled, the only way to avoid newline as a +break character is to write all the break characters in the file with no +newline at all, not even at the end of the file. When GNU extensions +are disabled, spaces, tabs and newlines are always considered as break +characters even if not included in the Break file. + +@item -i @var{file} +@itemx --ignore-file=@var{file} + +The file associated with this option contains a list of words which will +never be taken as keywords in concordance output. It is called the +@dfn{Ignore file}. The file contains exactly one word in each line; the +end of line separation of words is not subject to the value of the +@code{-S} option. + +There is a default Ignore file used by @code{ptx} when this option is +not specified, usually found in @file{/usr/local/lib/eign} if this has +not been changed at installation time. If you want to deactivate the +default Ignore file, specify @code{/dev/null} instead. + +@item -o @var{file} +@itemx --only-file=@var{file} + +The file associated with this option contains a list of words which will +be retained in concordance output, any word not mentioned in this file +is ignored. The file is called the @dfn{Only file}. The file contains +exactly one word in each line; the end of line separation of words is +not subject to the value of the @code{-S} option. + +There is no default for the Only file. In the case there are both an +Only file and an Ignore file, a word will be subject to be a keyword +only if it is given in the Only file and not given in the Ignore file. + +@item -r +@itemx --references + +On each input line, the leading sequence of non white characters will be +taken to be a reference that has the purpose of identifying this input +line on the produced permuted index. See @xref{Output formatting} for +more information about reference production. Using this option change +the default value for option @code{-S}. + +Using this option, the program does not try very hard to remove +references from contexts in output, but it succeeds in doing so +@emph{when} the context ends exactly at the newline. If option +@code{-r} is used with @code{-S} default value, or when GNU extensions +are disabled, this condition is always met and references are completely +excluded from the output contexts. + +@item -S @var{regexp} +@itemx --sentence-regexp=@var{regexp} + +This option selects which regular expression will describe the end of a +line or the end of a sentence. In fact, there is other distinction +between end of lines or end of sentences than the effect of this regular +expression, and input line boundaries have no special significance +outside this option. By default, when GNU extensions are enabled and if +@code{-r} option is not used, end of sentences are used. In this +case, the precise @var{regex} is imported from GNU emacs: + +@example +[.?!][]\"')@}]*\\($\\|\t\\| \\)[ \t\n]* +@end example + +Whenever GNU extensions are disabled or if @code{-r} option is used, end +of lines are used; in this case, the default @var{regexp} is just: + +@example +\n +@end example + +Using an empty REGEXP is equivalent to completely disabling end of line or end +of sentence recognition. In this case, the whole file is considered to +be a single big line or sentence. The user might want to disallow all +truncation flag generation as well, through option @code{-F ""}. +@xref{Regexps, , Syntax of Regular Expressions, emacs, The GNU Emacs +Manual}. + +When the keywords happen to be near the beginning of the input line or +sentence, this often creates an unused area at the beginning of the +output context line; when the keywords happen to be near the end of the +input line or sentence, this often creates an unused area at the end of +the output context line. The program tries to fill those unused areas +by wrapping around context in them; the tail of the input line or +sentence is used to fill the unused area on the left of the output line; +the head of the input line or sentence is used to fill the unused area +on the right of the output line. + +As a matter of convenience to the user, many usual backslashed escape +sequences, as found in the C language, are recognized and converted to +the corresponding characters by @code{ptx} itself. + +@item -W @var{regexp} +@itemx --word-regexp=@var{regexp} + +This option selects which regular expression will describe each keyword. +By default, if GNU extensions are enabled, a word is a sequence of +letters; the @var{regexp} used is @code{\w+}. When GNU extensions are +disabled, a word is by default anything which ends with a space, a tab +or a newline; the @var{regexp} used is @code{[^ \t\n]+}. + +An empty REGEXP is equivalent to not using this option, letting the +default dive in. @xref{Regexps, , Syntax of Regular Expressions, emacs, +The GNU Emacs Manual}. + +As a matter of convenience to the user, many usual backslashed escape +sequences, as found in the C language, are recognized and converted to +the corresponding characters by @code{ptx} itself. + +@end table + +@node Output formatting, , Input processing, Invoking ptx +@section Output formatting + +Output format is mainly controlled by @code{-O} and @code{-T} options, +described in the table below. When neither @code{-O} nor @code{-T} is +selected, and if GNU extensions are enabled, the program choose an +output format suited for a dumb terminal. Each keyword occurrence is +output to the center of one line, surrounded by its left and right +contexts. Each field is properly justified, so the concordance output +could readily be observed. As a special feature, if automatic +references are selected by option @code{-A} and are output before the +left context, that is, if option @code{-R} is @emph{not} selected, then +a colon is added after the reference; this nicely interfaces with GNU +Emacs @code{next-error} processing. In this default output format, each +white space character, like newline and tab, is merely changed to +exactly one space, with no special attempt to compress consecutive +spaces. This might change in the future. Except for those white space +characters, every other character of the underlying set of 256 +characters is transmitted verbatim. + +Output format is further controlled by the following options. + +@table @code + +@item -g @var{number} +@itemx --gap-size=@var{number} + +Select the size of the minimum white gap between the fields on the output +line. + +@item -w @var{number} +@itemx --width=@var{number} + +Select the output maximum width of each final line. If references are +used, they are included or excluded from the output maximum width +depending on the value of option @code{-R}. If this option is not +selected, that is, when references are output before the left context, +the output maximum width takes into account the maximum length of all +references. If this options is selected, that is, when references are +output after the right context, the output maximum width does not take +into account the space taken by references, nor the gap that precedes +them. + +@item -A +@itemx --auto-reference + +Select automatic references. Each input line will have an automatic +reference made up of the file name and the line ordinal, with a single +colon between them. However, the file name will be empty when standard +input is being read. If both @code{-A} and @code{-r} are selected, then +the input reference is still read and skipped, but the automatic +reference is used at output time, overriding the input reference. + +@item -R +@itemx --right-side-refs + +In default output format, when option @code{-R} is not used, any +reference produced by the effect of options @code{-r} or @code{-A} are +given to the far right of output lines, after the right context. In +default output format, when option @code{-R} is specified, references +are rather given to the beginning of each output line, before the left +context. For any other output format, option @code{-R} is almost +ignored, except for the fact that the width of references is @emph{not} +taken into account in total output width given by @code{-w} whenever +@code{-R} is selected. + +This option is automatically selected whenever GNU extensions are +disabled. + +@item -F @var{string} +@itemx --flac-truncation=@var{string} + +This option will request that any truncation in the output be reported +using the string @var{string}. Most output fields theoretically extend +towards the beginning or the end of the current line, or current +sentence, as selected with option @code{-S}. But there is a maximum +allowed output line width, changeable through option @code{-w}, which is +further divided into space for various output fields. When a field has +to be truncated because cannot extend until the beginning or the end of +the current line to fit in the, then a truncation occurs. By default, +the string used is a single slash, as in @code{-F /}. + +@var{string} may have more than one character, as in @code{-F ...}. +Also, in the particular case @var{string} is empty (@code{-F ""}), +truncation flagging is disabled, and no truncation marks are appended in +this case. + +As a matter of convenience to the user, many usual backslashed escape +sequences, as found in the C language, are recognized and converted to +the corresponding characters by @code{ptx} itself. + +@item -M @var{string} +@itemx --macro-name=@var{string} + +Select another @var{string} to be used instead of @samp{xx}, while +generating output suitable for @code{nroff}, @code{troff} or @TeX{}. + +@item -O +@itemx --format=roff + +Choose an output format suitable for @code{nroff} or @code{troff} +processing. Each output line will look like: + +@example +.xx "@var{tail}" "@var{before}" "@var{keyword_and_after}" "@var{head}" "@var{ref}" +@end example + +so it will be possible to write an @samp{.xx} roff macro to take care of +the output typesetting. This is the default output format when GNU +extensions are disabled. Option @samp{-M} might be used to change +@samp{xx} to another macro name. + +In this output format, each non-graphical character, like newline and +tab, is merely changed to exactly one space, with no special attempt to +compress consecutive spaces. Each quote character: @kbd{"} is doubled +so it will be correctly processed by @code{nroff} or @code{troff}. + +@item -T +@itemx --format=tex + +Choose an output format suitable for @TeX{} processing. Each output +line will look like: + +@example +\xx @{@var{tail}@}@{@var{before}@}@{@var{keyword}@}@{@var{after}@}@{@var{head}@}@{@var{ref}@} +@end example + +@noindent +so it will be possible to write write a @code{\xx} definition to take +care of the output typesetting. Note that when references are not being +produced, that is, neither option @code{-A} nor option @code{-r} is +selected, the last parameter of each @code{\xx} call is inhibited. +Option @samp{-M} might be used to change @samp{xx} to another macro +name. + +In this output format, some special characters, like @kbd{$}, @kbd{%}, +@kbd{&}, @kbd{#} and @kbd{_} are automatically protected with a +backslash. Curly brackets @kbd{@{}, @kbd{@}} are also protected with a +backslash, but also enclosed in a pair of dollar signs to force +mathematical mode. The backslash itself produces the sequence +@code{\backslash@{@}}. Circumflex and tilde diacritics produce the +sequence @code{^\@{ @}} and @code{~\@{ @}} respectively. Other +diacriticized characters of the underlying character set produce an +appropriate @TeX{} sequence as far as possible. The other non-graphical +characters, like newline and tab, and all others characters which are +not part of ASCII, are merely changed to exactly one space, with no +special attempt to compress consecutive spaces. Let me know how to +improve this special character processing for @TeX{}. + +@end table + +@node Compatibility, , Invoking ptx, Top +@chapter The GNU extensions to @code{ptx} + +This version of @code{ptx} contains a few features which do not exist in +System V @code{ptx}. These extra features are suppressed by using the +@samp{-G} command line option, unless overridden by other command line +options. Some GNU extensions cannot be recovered by overriding, so the +simple rule is to avoid @samp{-G} if you care about GNU extensions. +Here are the differences between this program and System V @code{ptx}. + +@itemize @bullet + +@item +This program can read many input files at once, it always writes the +resulting concordance on standard output. On the other end, System V +@code{ptx} reads only one file and produce the result on standard output +or, if a second @var{file} parameter is given on the command, to that +@var{file}. + +Having output parameters not introduced by options is a quite dangerous +practice which GNU avoids as far as possible. So, for using @code{ptx} +portably between GNU and System V, you should pay attention to always +use it with a single input file, and always expect the result on +standard output. You might also want to automatically configure in a +@samp{-G} option to @code{ptx} calls in products using @code{ptx}, if +the configurator finds that the installed @code{ptx} accepts @samp{-G}. + +@item +The only options available in System V @code{ptx} are options @samp{-b}, +@samp{-f}, @samp{-g}, @samp{-i}, @samp{-o}, @samp{-r}, @samp{-t} and +@samp{-w}. All other options are GNU extensions and are not repeated in +this enumeration. Moreover, some options have a slightly different +meaning when GNU extensions are enabled, as explained below. + +@item +By default, concordance output is not formatted for @code{troff} or +@code{nroff}. It is rather formatted for a dumb terminal. @code{troff} +or @code{nroff} output may still be selected through option @code{-O}. + +@item +Unless @code{-R} option is used, the maximum reference width is +subtracted from the total output line width. With GNU extensions +disabled, width of references is not taken into account in the output +line width computations. + +@item +All 256 characters, even @kbd{NUL}s, are always read and processed from +input file with no adverse effect, even if GNU extensions are disabled. +However, System V @code{ptx} does not accept 8-bit characters, a few +control characters are rejected, and the tilda @kbd{~} is condemned. + +@item +Input line length is only limited by available memory, even if GNU +extensions are disabled. However, System V @code{ptx} processes only +the first 200 characters in each line. + +@item +The break (non-word) characters default to be every character except all +letters of the underlying character set, diacriticized or not. When GNU +extensions are disabled, the break characters default to space, tab and +newline only. + +@item +The program makes better use of output line width. If GNU extensions +are disabled, the program rather tries to imitate System V @code{ptx}, +but still, there are some slight disposition glitches this program does +not completely reproduce. + +@item +The user can specify both an Ignore file and an Only file. This is not +allowed with System V @code{ptx}. + +@end itemize + +@bye diff --git a/gnu/usr.bin/ptx/regex.h b/gnu/usr.bin/ptx/regex.h new file mode 100644 index 000000000000..a495005ce936 --- /dev/null +++ b/gnu/usr.bin/ptx/regex.h @@ -0,0 +1,490 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. + + 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, 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. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#ifdef VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +#include <stddef.h> +#endif + + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS (1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \<digit> matches <digit>. + If not set, then \<digit> is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +#undef RE_DUP_MAX +#endif +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Not implemented. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +struct re_pattern_buffer +{ +/* [[[begin pattern_buffer]]] */ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are + sometimes used as array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses + the fastmap, if there is one, to skip over impossible + starting points for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation + is applied to a pattern when it is compiled and to a string + when it is matched. */ + char *translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see + whether or not we should use the fastmap, so we don't set + this absolutely perfectly; see `re_compile_fastmap' (the + `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + + +/* search.c (search_buffer) in Emacs needs this one opcode value. It is + defined both in `regex.c' and here. */ +#define RE_EXACTN_VALUE 1 + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +#define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, int length, + struct re_pattern_buffer *buffer)); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int range, struct re_registers *regs)); + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int stop)); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/usr.bin/ptx/texinfo.tex b/gnu/usr.bin/ptx/texinfo.tex new file mode 100644 index 000000000000..ce11b7b828e0 --- /dev/null +++ b/gnu/usr.bin/ptx/texinfo.tex @@ -0,0 +1,4053 @@ +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc. + +%This texinfo.tex file 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, or (at +%your option) any later version. + +%This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write +%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, +%USA. + + +%In other words, you are welcome to use, share and improve this program. +%You are forbidden to forbid anyone else to use, share and improve +%what you give them. Help stamp out software-hoarding! + +\def\texinfoversion{2.115} +\message{Loading texinfo package [Version \texinfoversion]:} + +% Print the version number if in a .fmt file. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{}} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +\def\tie{\penalty 10000\ } % Save plain tex definition of ~. + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +%---------------------Begin change----------------------- +% +%%%% For @cropmarks command. +% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen \topandbottommargin +\newdimen \outerhsize \newdimen \outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in +% +%---------------------End change----------------------- + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions itself, but you have to call it yourself. +\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} +\def\onepageout#1{\hoffset=\normaloffset +\ifodd\pageno \advance\hoffset by \bindingoffset +\else \advance\hoffset by -\bindingoffset\fi +{\escapechar=`\\\relax % makes sure backslash is used in output files. +\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}% +{\let\hsize=\pagewidth \makefootline}}}% +\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi} + +%%%% For @cropmarks command %%%% + +% Here is a modification of the main output routine for Near East Publications +% This provides right-angle cropmarks at all four corners. +% The contents of the page are centerlined into the cropmarks, +% and any desired binding offset is added as an \hskip on either +% site of the centerlined box. (P. A. MacKay, 12 November, 1986) +% +\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up +{\escapechar=`\\\relax % makes sure backslash is used in output files. + \shipout + \vbox to \outervsize{\hsize=\outerhsize + \vbox{\line{\ewtop\hfill\ewtop}} + \nointerlineskip + \line{\vbox{\moveleft\cornerthick\nstop} + \hfill + \vbox{\moveright\cornerthick\nstop}} + \vskip \topandbottommargin + \centerline{\ifodd\pageno\hskip\bindingoffset\fi + \vbox{ + {\let\hsize=\pagewidth \makeheadline} + \pagebody{#1} + {\let\hsize=\pagewidth \makefootline}} + \ifodd\pageno\else\hskip\bindingoffset\fi} + \vskip \topandbottommargin plus1fill minus1fill + \boxmaxdepth\cornerthick + \line{\vbox{\moveleft\cornerthick\nsbot} + \hfill + \vbox{\moveright\cornerthick\nsbot}} + \nointerlineskip + \vbox{\line{\ewbot\hfill\ewbot}} + }} + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi} +% +% Do @cropmarks to get crop marks +\def\cropmarks{\let\onepageout=\croppageout } + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type <Return> to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = \baselineskip +\def\singlespace{% +% Why was this kern here? It messes up equalizing space above and below +% environments. --karl, 6may93 +%{\advance \baselineskip by -\singlespaceskip +%\kern \baselineskip}% +\baselineskip=\singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt \char '100}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. + +\def\mylbrace {{\tt \char '173}} +\def\myrbrace {{\tt \char '175}} +\let\{=\mylbrace +\let\}=\myrbrace + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % We do @comment here in case we are called inside an environment, + % such as @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output some dots + +\def\dots{$\ldots$} + +% @page forces the start of a new page + +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. + +\def\include{\parsearg\includezzz} +%Use \input\thisfile to avoid blank after \input, which may be an active +%char (in which case the blank would become the \input argument). +%The grouping keeps the value of \thisfile correct even when @include +%is nested. +\def\includezzz #1{\begingroup +\def\thisfile{#1}\input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\par \vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + \long\def\doignoretext##1\end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}} +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% +\def\set{\parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi +} +\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex always succeeds; we read the text following, through @end +% iftex). But `@end iftex' should be valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\defineunmatchedend{iftex} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\let\lastnode=\relax} + +\let\refill=\relax + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \readauxfile + \opencontents + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + \comment % Ignore the actual filename. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\font\textrm=cmr12 +\font\texttt=cmtt12 +\else +\font\textrm=cmr10 scaled \mainmagstep +\font\texttt=cmtt10 scaled \mainmagstep +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\font\textbf=cmb10 scaled \mainmagstep +\font\textit=cmti10 scaled \mainmagstep +\font\textsl=cmsl10 scaled \mainmagstep +\font\textsf=cmss10 scaled \mainmagstep +\font\textsc=cmcsc10 scaled \mainmagstep +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\font\defbf=cmbx10 scaled \magstep1 %was 1314 +\font\deftt=cmtt10 scaled \magstep1 +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\font\ninett=cmtt9 +\font\indrm=cmr9 +\font\indit=cmsl9 +\let\indsl=\indit +\let\indtt=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\let\indsc=\indrm +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for headings +\font\chaprm=cmbx12 scaled \magstep2 +\font\chapit=cmti12 scaled \magstep2 +\font\chapsl=cmsl12 scaled \magstep2 +\font\chaptt=cmtt12 scaled \magstep2 +\font\chapsf=cmss12 scaled \magstep2 +\let\chapbf=\chaprm +\font\chapsc=cmcsc10 scaled\magstep3 +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +\font\secrm=cmbx12 scaled \magstep1 +\font\secit=cmti12 scaled \magstep1 +\font\secsl=cmsl12 scaled \magstep1 +\font\sectt=cmtt12 scaled \magstep1 +\font\secsf=cmss12 scaled \magstep1 +\font\secbf=cmbx12 scaled \magstep1 +\font\secsc=cmcsc10 scaled\magstep2 +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad. +% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded. +% \font\ssecsl=cmsl10 scaled \magstep1 +% \font\ssectt=cmtt10 scaled \magstep1 +% \font\ssecsf=cmss10 scaled \magstep1 + +%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx. +%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than +%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1. +%\font\ssectt=cmtt10 scaled 1315 +%\font\ssecsf=cmss10 scaled 1315 + +%\let\ssecbf=\ssecrm + +\font\ssecrm=cmbx12 scaled \magstephalf +\font\ssecit=cmti12 scaled \magstephalf +\font\ssecsl=cmsl12 scaled \magstephalf +\font\ssectt=cmtt12 scaled \magstephalf +\font\ssecsf=cmss12 scaled \magstephalf +\font\ssecbf=cmbx12 scaled \magstephalf +\font\ssecsc=cmcsc10 scaled \magstep1 +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled \magstep1 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% Fonts for title page: +\font\titlerm = cmbx12 scaled \magstep3 +\let\authorrm = \secrm + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current. Plain TeX does, for example, +% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need +% to redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \resetmathfonts} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \resetmathfonts} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \resetmathfonts} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \resetmathfonts} +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy + \resetmathfonts} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\font\shortcontrm=cmr12 +\font\shortcontbf=cmbx12 +\font\shortcontsl=cmsl12 + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \nohyphenation \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont = \t +%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null} +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overful hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate an a dash. +% -- rms. +{ +\catcode`\-=\active +\catcode`\_=\active +\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} +% The following is used by \doprintindex to insure that long function names +% wrap around. It is necessary for - and _ to be active before the index is +% read from the file, as \entry parses the arguments long before \code is +% ever called. -- mycroft +\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder} +} +\def\realdash{-} +\def\realunder{_} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\normalunderscore\discretionary{}{}{}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else\tclose{\look}\fi +\else\tclose{\look}\fi} + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of +% @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +\def\l#1{{\li #1}\null} % + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\def\titlefont#1{{\titlerm #1}} + +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefont{##1}} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} +\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} +\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\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\year} + +% Use this if you want the Month Day, Year style of output. +%\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} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + +\message{tables,} + +% @tabs -- simple alignment + +% These don't work. For one thing, \+ is defined as outer. +% So these macros cannot even be defined. + +%\def\tabs{\parsearg\tabszzz} +%\def\tabszzz #1{\settabs\+#1\cr} +%\def\tabline{\parsearg\tablinezzz} +%\def\tablinezzz #1{\+#1\cr} +%\def\&{&} + +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + %{\parskip = 0in + %\par + %}% + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}\ignorespaces% + \endgroup% + \itemxneedsnegativevskiptrue% + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Neccessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemsize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{\in hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. + +\def\newindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +\def\synindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\char{\realbackslash char}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\copyright{\realbackslash copyright }% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other +@gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. + +\def\doind #1#2{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% Expand all macros now EXCEPT \folio +\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now +% so it will be output as is; and it will print as backslash in the indx. +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}}}% +\temp }% +}\penalty\count10}} + +\def\dosubind #1#2#3{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% +\def\rawbackslashxx{\indexbackslash}% +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2 #3}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% +\temp }% +}\penalty\count10}} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% This is what you call to cause a particular index to get printed. +% Write +% @unnumbered Function Index +% @printindex fn + +\def\printindex{\parsearg\doprintindex} + +\def\doprintindex#1{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other + \catcode`\~=\other + \indexbreaks + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \begindoublecolumns + % + % See if the index file exists and is nonempty. + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + (Index is nonexistent) + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + (Index is empty) + \else + \input \jobname.#1s + \fi + \fi + \closein 1 + \enddoublecolumns + \Etex +} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent=2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kluged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +%% Define two-column mode, which is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % Grab any single-column material above us. + \output = {\global\setbox\partialpage + =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% + \eject + % + % Now switch to the double-column output routine. + \output={\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it once. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +- < + % 1pt) as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\catcode `\@=\other +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount \chapno +\newcount \secno \secno=0 +\newcount \subsecno \subsecno=0 +\newcount \subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount \appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +\newwrite \contentsfile +% This is called from \setfilename. +\def\opencontents{\openout \contentsfile = \jobname.toc} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\if \pageno<0 % +\errmessage{@#1 not allowed after generating table of contents}\fi +% +} + +\def\chapternofonts{% +\let\rawbackslash=\relax% +\let\frenchspacing=\relax% +\def\result{\realbackslash result} +\def\equiv{\realbackslash equiv} +\def\expansion{\realbackslash expansion} +\def\print{\realbackslash print} +\def\TeX{\realbackslash TeX} +\def\dots{\realbackslash dots} +\def\copyright{\realbackslash copyright} +\def\tt{\realbackslash tt} +\def\bf{\realbackslash bf } +\def\w{\realbackslash w} +\def\less{\realbackslash less} +\def\gtr{\realbackslash gtr} +\def\hat{\realbackslash hat} +\def\char{\realbackslash char} +\def\tclose##1{\realbackslash tclose {##1}} +\def\code##1{\realbackslash code {##1}} +\def\samp##1{\realbackslash samp {##1}} +\def\r##1{\realbackslash r {##1}} +\def\b##1{\realbackslash b {##1}} +\def\key##1{\realbackslash key {##1}} +\def\file##1{\realbackslash file {##1}} +\def\kbd##1{\realbackslash kbd {##1}} +% These are redefined because @smartitalic wouldn't work inside xdef. +\def\i##1{\realbackslash i {##1}} +\def\cite##1{\realbackslash cite {##1}} +\def\var##1{\realbackslash var {##1}} +\def\emph##1{\realbackslash emph {##1}} +\def\dfn##1{\realbackslash dfn {##1}} +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{Chapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{Appendix \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{Appendix \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the<toks register> to achieve this: TeX expands \the<toks> only once, +% simply yielding the contents of the <toks register>. +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appenixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry % + {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry{#1}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and +% such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{ +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\message{toc printing,} + +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{Table of Contents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{Short Contents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm Appendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in in \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +% +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +\let\ptexequiv = \equiv + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +\def\point{$\star$} + +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} + +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup +\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 +\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 +\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie +\catcode `\%=14 +\catcode 43=12 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \cartouche: draw rectangle w/rounded corners around argument +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +% This macro is +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller interline space and fonts for small examples. + \baselineskip 10pt + \indexfonts \tt + \rawbackslash % output the \ character from the current font + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking and narrows the margins. +% +\def\quotation{% +\begingroup\inENV %This group ends at the end of the @quotation body +{\parskip=0pt % because we will skip by \parskip too, later +\aboveenvbreak}% +\singlespace +\parindent=0pt +\let\Equotation = \nonfillfinish +% @cartouche defines \nonarrowing to inhibit narrowing +% at next level down. +\ifx\nonarrowing\relax +\advance \leftskip by \lispnarrowing +\advance \rightskip by \lispnarrowing +\exdentamount=\lispnarrowing +\let\nonarrowing=\relax +\fi} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % +\global\advance\parencount by 1 } +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. +% also in that case restore the outer-level definition of (. +\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi +\global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does, putting the result in \tptemp. +% +\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}% + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + \removeemptybraces#2\relax + #1{\tptemp}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\functionparens +\code{#1}% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\code{#1} #2}{Function}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\code{#2} #3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop {Funny Method} foo-class frobnicate argument + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +} + +% @defmethod == @defop Method + +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} + +\def\defmethodheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% entry in function index +\begingroup\defname {#2}{Method on #1}% +\defunargs {#3}\endgroup % +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name. +\def\deftypevarheader #1#2{% +\doind {vr}{\code{#2}}% Make entry in variables index +\begingroup\defname {\code{#1} #2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% +\begingroup\defname {\code{#2} #3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + +\message{cross reference,} +% Define cross-reference macros +\newwrite \auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% \setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% For \xrefX, #1 is the node name, #2 the name of the Info +% cross-reference, #3 the printed node name, #4 the name of the Info +% file, #5 the name of the printed manual. All but the node name can be +% omitted. +% +\def\pxref#1{see \xrefX[#1,,,,,,,]} +\def\xref#1{See \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup% +\def\printedmanual{\ignorespaces #5}% +\def\printednodename{\ignorespaces #3}% +% +\setbox1=\hbox{\printedmanual}% +\setbox0=\hbox{\printednodename}% +\ifdim \wd0=0pt% +% No printed node name was explicitly given. +\ifx SETxref-automatic-section-title % +% This line should make the actual chapter or section title appear inside +% the square brackets. Use the real section title if we have it. +\ifdim \wd1>0pt% +% It is in another manual, so we don't have it. +\def\printednodename{\ignorespaces #1} \else% +% We know the real title if we have the xref values. +\ifhavexrefs \def\printednodename{\refx{#1-title}}% +% Otherwise just copy the Info node name. +\else \def\printednodename{\ignorespaces #1} \fi% +\fi\def\printednodename{#1-title}% +\else% This line just uses the node name. +\def\printednodename{\ignorespaces #1}% +\fi% ends \ifx SETxref-automatic-section-title +\fi% ends \ifdim \wd0 +% +% +% If we use \unhbox0 and \unhbox1 to print the node names, TeX does +% not insert empty discretionaries after hyphens, which means that it +% will not find a line break at a hyphen in a node names. Since some +% manuals are best written with fairly long node names, containing +% hyphens, this is a loss. Therefore, we simply give the text of +% the node name again, so it is as if TeX is seeing it for the first +% time. +\ifdim \wd1>0pt +section ``\printednodename'' in \cite{\printedmanual}% +\else% +\turnoffactive% +\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}% +\fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \turnoffactive so that punctuation chars such as underscore +% work in node names. +\def\dosetq #1#2{{\let\folio=0 \turnoffactive% +\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% +\next}} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 Chapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + $\langle$un\-de\-fined$\rangle$% + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% Read the last existing aux file, if any. No error if none exists. + +% This is the macro invoked by entries in the aux file. +\def\xrdef #1#2{ +{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} + +\def\readauxfile{% +\begingroup +\catcode `\^^@=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\^^C=\other +\catcode `\^^D=\other +\catcode `\^^E=\other +\catcode `\^^F=\other +\catcode `\^^G=\other +\catcode `\^^H=\other +\catcode `\=\other +\catcode `\^^L=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode 26=\other +\catcode `\^^[=\other +\catcode `\^^\=\other +\catcode `\^^]=\other +\catcode `\^^^=\other +\catcode `\^^_=\other +\catcode `\@=\other +\catcode `\^=\other +\catcode `\~=\other +\catcode `\[=\other +\catcode `\]=\other +\catcode`\"=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode `\$=\other +\catcode `\#=\other +\catcode `\&=\other +% `\+ does not work, so use 43. +\catcode 43=\other +% the aux file uses ' as the escape. +% Turn off \ as an escape so we do not lose on +% entries which were dumped with control sequences in their names. +% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ +% Reference to such entries still does not work the way one would wish, +% but at least they do not bomb out when the aux file is read in. +\catcode `\{=1 \catcode `\}=2 +\catcode `\%=\other +\catcode `\'=0 +\catcode `\\=\other +\openin 1 \jobname.aux +\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue +\global\warnedobstrue +\fi +% Open the new aux file. Tex will close it automatically at exit. +\openout \auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only.. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +\long\gdef\footnotezzz#1{\insert\footins{% + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + #1\strut}% +} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + + +% End of control word definitions. + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +%\hsize = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt + +\global\pagewidth=\hsize +\global\pageheight=\vsize + +\global\let\smalllisp=\smalllispx +\global\let\smallexample=\smalllispx +\global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt \char '042}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt \char '176}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +% \lvvmode is equivalent in function to \leavevmode. +% Using \leavevmode runs into trouble when written out to +% an index file due to the expansion of \leavevmode into ``\unhbox +% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our +% magic tricks with @. +\def\lvvmode{\vbox to 0pt{}} + +\catcode`\|=\active +\def|{{\tt \char '174}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +\def\turnoffactive{\let"=\normaldoublequote +\let~=\normaltilde +\let^=\normalcaret +\let_=\normalunderscore +\let|=\normalverticalbar +\let<=\normalless +\let>=\normalgreater +\let+=\normalplus} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi} + +%% These look ok in all fonts, so just make them not special. The @rm below +%% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/gnu/usr.bin/ptx/xmalloc.c b/gnu/usr.bin/ptx/xmalloc.c new file mode 100644 index 000000000000..58a81b5abbce --- /dev/null +++ b/gnu/usr.bin/ptx/xmalloc.c @@ -0,0 +1,88 @@ +/* xmalloc.c -- malloc with out of memory checking + Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc. + + 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, 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. */ + +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#if __STDC__ +#define VOID void +#else +#define VOID char +#endif + +#include <sys/types.h> + +#if STDC_HEADERS +#include <stdlib.h> +#else +VOID *malloc (); +VOID *realloc (); +void free (); +#endif + +#if __STDC__ && defined (HAVE_VPRINTF) +void error (int, int, char const *, ...); +#else +void error (); +#endif + +/* Allocate N bytes of memory dynamically, with error checking. */ + +VOID * +xmalloc (n) + size_t n; +{ + VOID *p; + + p = malloc (n); + if (p == 0) + /* Must exit with 2 for `cmp'. */ + error (2, 0, "virtual memory exhausted"); + return p; +} + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. + If P is NULL, run xmalloc. + If N is 0, run free and return NULL. */ + +VOID * +xrealloc (p, n) + VOID *p; + size_t n; +{ + if (p == 0) + return xmalloc (n); + if (n == 0) + { + free (p); + return 0; + } + p = realloc (p, n); + if (p == 0) + /* Must exit with 2 for `cmp'. */ + error (2, 0, "virtual memory exhausted"); + return p; +} |