libg++/COPYING 644 473 0 30310 4677677671 6231 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 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 license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our 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. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 a 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 tell them 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. 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 Agreement 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 work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 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 General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual 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 General Public License. d) 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. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying 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. 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. 7. 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 the 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 the license, you may choose any version ever published by the Free Software Foundation. 8. 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 9. 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. 10. 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 humanity, 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. Copyright (C) 19yy 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 1, 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) 19xx 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 a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! 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 a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the programlibg++/README 644 473 0 27426 4677677671 6074 This is version 1.37.0 of libg++, the GNU C++ class library. Release date Wed Feb 28 05:28:27 1990 Doug Lea (dl at g.oswego.edu) * Please skim through this once BEFORE attempting to make and install libg++. * Contents * g++ source files are in the ./src directory * Some simple tests and demo programs are in ./tests * Header files are in ./g++-include * documentation is in ./libg++.texinfo. * Some miscellaneous files of possible interest are in ./etc (These files are not officially a part of the libg++ distribution, and are subject to arbitrary changes, deletions, etc. from release to release.) * Pre-installation * Install a version of g++ with at least as high a version number as this version of libg++. You also need gcc installed. * If there is a version of the GNU as (gas) assembler that works on your machine, get it, and install it as gcc-as, in whatever lib directory holds gcc-cc1plus. Otherwise, you may have to remake g++ with -DFASCIST_ASSEMBLER in CFLAGS, and disable the -PIPE_AS flag in the libg++ Makefile. * If, for some reason, you are attempting to use libg++ with some other C++-2.0 compiler (like cfront), the only intentional deviation from the 2.0 standard used in libg++ is the use of named return values. If you would like to volunteer to correctly #ifdef around these, I will incorporate these changes into a future release. If you encounter any other problematic g++-specific idioms (outside of incremental linking, wrappers, and the like, tested only in the test files, but otherwise unused in the library), please report them. * Installation (see libg++.texinfo more more details) * Except for how to set the `PWD' make variable (which you must manually change if you do not use GNU make), the Makefiles are reported to be compatible with all flavors of `make'. * Check the declared indicated pathnames, etc. in the top-level Makefile Be sure to use USG-oriented switches if you run SystemV unix. On MIPS-based machines using g++/gcc-1.37, it may be necessary to disable optimization to avoid compiler limitations. If you run into problems, check through system-dependent #defines in g++-include/stdio.h, g++-include/math.h and g++-include/values.h, especially, and report any incompatibilities or problems to bug-lib-g++@prep.ai.mit.edu. * Choose functionality flags. In the libg++ Makefile, `XTRAFLAGS' are selectable. By default, none of these are enabled: -DEFAULT_filebuf, if included in XTRAFLAGS, causes standard cin, cout, and cerr streams to bypass your libc stdio facilities. I know of no system for which this is absolutely required. However, if there are known bugs with your stdio implementation, or if you wish to give up some functionality in order to be conservative, then select this. If you use this, expect an innocuous difference between the expected and obtained results of tFile in how the final status of standard streams is printed. -DNO_GNULIB3 suppresses compilation of a dummy `main', which calls global constructors and destructors around a user main. Select this if you have made alternative arrangements for doing this. -DCOFF_ENCAPSULATE is required for systems in which all executables use GNU COFF encapsulation. -DNO_LINE_BUFFER_STREAMBUF suppresses line-buffering (automatic flushing of output whenever a newline is encountered). Selecting this may result in slightly smaller code, but will require manual flushing when lines are expected to be printed right when they are written. -DNO_LIBGXX_MALLOC suppresses compilation of libg++ malloc routines, thus causing all malloc, free, realloc, operator new() and operator delete() calls to go through your libc version of malloc. Select this if your system requires a the system version of malloc (possibly necessary on some shared memory multiprocessors, since libg++ malloc does not contain any concurrency control), or, perhaps, if your applications are specially tuned for or otherwise work better with your system malloc. -DMALLOC_STATS compiles statistics counting into libg++ malloc (but also slows it down a little). Select this if you are interested in examining the performance of libg++ malloc. (I welcome this, and would be grateful to receive statistics (printed via `malloc_stats()') for programs with heavy dynamic allocation requirements.) * Other compilation flags are tunable, but the default versions should normally suffice. * type `make all', or, step-by-step: `make src' -- to compile libg++.a `make tests' -- to make some tests/demos of libg++. This will first compile tests, then run them, then diff the results against expected results. `make install' -- to install libg++.a and include directories `make etc' -- (optional) to compile various other things `make gperf' -- (optional) to compile Doug Schmidt's perfect hash function generator. This program illustrates many of the new C++ 2.0 features available in G++, including multiple inheritance and static member functions. * Installing Documentation If you are a systems administrator installing libg++ for others, please make the documentation available to users! The libg++.texinfo file may be formatted as a paper document by * Get a copy of texinfo.tex. This file defines various tex macros used in libg++.texinfo One is in the gcc release. You can temporarily copy it into the current directory. * Run tex on libg++.texinfo and do whatever you normally do from there to print it. It may be made into an emacs info file by * Inside emacs, run M-x texinfo-format-buffer on libg++.texinfo. * Save the resulting files: libg++ libg++-1 libg++-2 ... * Copy these files into your emacs info directory (normally somewhere like /usr/gnu/emacs/info). * If you have not done so before, edit the emacs/info/dir file to add a libg++ node, by inserting a line like * Libg++: (libg++). The GNU C++ Library to the bottom of the file. * General compilation notes By default, everything is compiled with the g++/gcc -Wall flag enabled. This causes g++ to produce numerous diagnostic warnings and reminders. This is perfectly normal. Only true error messages, which cause the `makes' to halt indicate real problems. If you do not like to look at the warnings, disable the -Wall in the Makefile. -Wall is enabled because, if there are true errors, warnings leading up to them may prove helpful. * Notes on compiling and running libg++/tests test0 and tCurses are not automatically run through `checktests'. You must run them manually: test0 only tests the dynamic linking capabilities of g++, which are not exploited in the rest of the library. The test is in libg++/tests since it requires include files, etc., not otherwise present in the g++ release. To run test0, you can type `test.shell' when asked for a file name, and get a csh shell loaded, if dynamic linking is working. If you exit from the shell, you should be back in test0, and you can type `test.bye2' to cleanly exit. With the current g++, tests/test0, and incremental linking in general should work on most machines. If it does not, you may even have trouble compiling it. You can do `touch tests/test0', and continue if this happens to you. tCurses attempts to place one of each curses library primitive (boxes, strings, numbers...) on your screen, and asks for some input, to test curses input routines. Since there is no way to describe the output in a system- and terminal- independent way, you will have to be the judge of whether it works acceptably. tCurses (and the curses-based classes generally) may fail on the Sequent and perhaps other systems with unusual or old curses library implementations if you do not end input with a instead of the normal . It is a very good idea to also cd to the test directory and run tests manually, to see what they do. Compiling and running the tests consumes a fair amount of time and disk space! Some reported diffs may be perfectly reasonable, owing to things like floating point precision differences: The expected.out file was created on a Sun4/110. Some tRational and tFix results depend on floating point precision and may generate slightly different output on different machines. tRandom seeds some random-numbers in a way that also relies on floating-point representations -- Your output should be numerically similar, but probably not identical. * changes from libg++-1.36.1 * Most utility classes and functions are now in stand-alone .cc and/or .h files. This should generate smaller exectuables, and, sometimes faster compilation. In particular, istream.h, and ostream.h are now separately includable. If you only need one, you don't have to get the other. * The Plex classes now understand `const'. The `changes' and `changed' member functions were removed, since it is now possible to avoid changes in Plex structures by using const versions. * class RandomInteger is available, courtesy of John Reidl. * PlotFile3D, a 3D plot class is in libg++/etc. It will be incorporated into libg++ proper for the next release, perhaps with a few changes. Thanks to Tom Ngo. * various and sundry bug fixes, minor enhancements, and/or portability improvements as described in the ChangeLog. * The file etc/HINTS is an emacs RMAIL file that contains recent bug-lib-g++ list mail and related messages that may be useful. * Known bugs and problems * Support for the DecStation3100 and other MIPS-based machines is still uncertain. * Lots of other information is in the libg++.texinfo file. It really is very important to actually read the documentation before using library classes. Examination of the demo files in the test directory may also be useful. (Note however, that the demo files are merely designed to test examples of each class capability, and are not especially good examples of client functions that might use these classes.) * There is now a gnu libg++ mailing list (bug-lib-g++@prep.ai.mit.edu) and associated usenet gnu news group. * You will be performing a valuable service if you use libg++ classes and report back any comments, and suggestions, or bugs, preferably to the bug-lib-g++ list. Your feedback is extremely helpful in efforts to make libg++ as useful and reliable as possible. * See file `etc/release.log' for changes from previous versions * I continue to solicit * bug reports. * suggestions. * comments. * questions about installing and using libg++ * other contributions to be incorporated into libg++. * sample programs using libg++. Often, the best place to send such things is bug-lib-g++@prep.ai.mit.edu, although direct mail to me is also welcome. * Good luck! Doug Lea, Computer Science Dept., SUNY Oswego, Oswego, NY, 13126 (315)341-2367 email: dl@oswego.edu or dl%oswego.edu@nisc.nyser.net UUCP :...cornell!devvax!oswego!dl or ...rutgers!sunybcs!oswego!dl ggestions. * comments. * questions about installing and using libg++ * other contributions to be incorporated into libg++. * sample programs using libg++. Often, the best place to send such things is bug-lib-g++@prep.ai.mitlibg++/Makefile 644 473 0 21775 4700646040 6622 # Makefile for GNU C++ class library (libg++) # Copyright (C) 1989 Free Software Foundation, Inc. # written by Doug Lea (dl@rocky.oswego.edu) #This file is part of GNU libg++. #GNU libg++ 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 1, or (at your option) #any later version. #GNU libg++ 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 GNU libg++; see the file COPYING. If not, write to #the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ########################################################################### # # Directories, paths, compilation flags and program names. # # Please make sure these are correct. # # ------ source locations # Manually set PWD to *this* directory if you are not using gnu make #PWD := $(shell pwd) PWD=/archiv/gnu/libg++ # source include directory SRCIDIR= $(PWD)/g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' # set `prefix' to something else if you want to install things # in nonstandard places prefix =/usr/local # libg++.a destination LIBDIR = $(prefix)/lib LIBGPLUS = Slibg++.a # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags #OSFLAG= OSFLAG = -DUSG # other compilation control flags -- use any combination # use this only if you have a strange stdio implementation #XTRAFLAGS = -DDEFAULT_filebuf # use this if you do not want gnulib3 in libg++.a #XTRAFLAGS = -DNO_GNULIB3 # use this if you need COFF encapulation defined in gnulib3 #XTRAFLAGS = -DCOFF_ENCAPSULATE # use this if you want to disable line buffering for stream output #XTRAFLAGS = -DNO_LINE_BUFFER_STREAMBUF # Use this to disable placing libg++ version of malloc in libg++.a #XTRAFLAGS = -DNO_LIBGXX_MALLOC # Please use this & send me some results of malloc_stats() sometime # (it is off by default, since stat gathering hurts performance) #XTRAFLAGS = -DMALLOC_STATS # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install #INSTALL=install -c INSTALL=cp # ranlib if necessary RANLIB=gnuranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader #LDXX = $(LIBDIR)/gcc-ld LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch #DEBUG_FLAGS= -g DEBUG_FLAGS= #use this only if you like to look at lots of useless messages #VERBOSITY_FLAGS= -Wall -v VERBOSITY_FLAGS= GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) #use this only if you use GNU as (gas) or other assemblers that #can read from pipes. PIPE_AS= -pipe #PIPE_AS= # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(XTRAFLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(XTRAFLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(PWD)/src -lg++ -lm $(OSLDFLAG) ########################################################################### # # compilation actions # src: FORCE (cd src; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)" VPATH="$(SRCIDIR)") tests: FORCE (cd tests; $(MAKE) checktests GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") etc: FORCE (cd etc; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") gperf: FORCE (cd gperf; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" prefix="$(prefix)") genclass: genclass.sh echo "/^PROTODIR=/c\\" > sedscript echo "PROTODIR=$(IDIR)" >> sedscript sed < genclass.sh > genclass -f sedscript chmod 0755 genclass rm -f sedscript #to force sub-makes FORCE: ########################################################################### # # Installation # all: src tests install etc gperf install: install-libg++.a install-genclass install-include-files install-libg++.a: src (cd src; $(INSTALL) libg++.a $(LIBDIR)/$(LIBGPLUS)) $(RANLIB) $(LIBDIR)/$(LIBGPLUS) install-genclass: genclass $(INSTALL) genclass $(BINDIR) install-include-files: -mkdir $(IDIR) -mkdir $(IDIR)/sys -cd $(SRCIDIR); \ FILES=`find . ! -type d -print`; \ cd $(IDIR); \ rm -fr $$FILES; \ rm -f Stack.ccP Queue.ccP Deque.ccP; \ cd $(SRCIDIR); \ FILES=`find . ! -type d -print`; \ for file in $$FILES; do \ rm -f $(IDIR)/$$file; \ cp $$file $(IDIR)/$$file; \ chmod 0444 $(IDIR)/$$file; \ echo $$file installed; \ done ########################################################################### # # Destructors # clean: (cd src; $(MAKE) clean) (cd tests; $(MAKE) clean) (cd etc; $(MAKE) clean) (cd gperf; $(MAKE) realclean) -rm -f genclass libg++.info* libg++.?? libg++.??s libg++.log libg++.toc libg++.*aux -rm -f *.orig src/*.orig tests/*.orig etc/*.orig g++-include/*.orig g++-include/sys/*.orig -rm -f *~ src/*~ tests/*~ etc/*~ g++-include/*~ g++-include/sys/*~ -rm -f a.out src/a.out tests/a.out etc/a.out -rm -f *.s src/*.s tests/*.s etc/*.s ########################################################################### # # Some helpful things for folks on Suns, from Ron Guilmette # NOTE: these do not refer to libg++, but might be helpful in configuration # with MCC/ESKIT systems SUN_INCLUDE_SUBDIRS=\ arpa \ pixrect \ rpcsvc \ sun \ sundev \ suntool \ sunwindow \ sys # WARNING! If you add sys/time.h to the list below, it will mess up the generation # of the sun-incl-patches file (see below). SUN_INCLUDE_FILES=\ netdb.h \ signal.h \ strings.h \ time.h \ arpa/inet.h \ pixrect/memvar.h \ pixrect/pixfont.h \ pixrect/pixrect.h \ pixrect/pixrect_hs.h \ pixrect/traprop.h \ rpcsvc/rstat.h \ sun/fbio.h \ sundev/kbio.h \ sundev/msio.h \ sundev/vuid_event.h \ suntool/canvas.h \ suntool/icon.h \ suntool/icon_load.h \ suntool/panel.h \ suntool/scrollbar.h \ suntool/sunview.h \ suntool/walkmenu.h \ suntool/window.h \ suntool/wmgr.h \ sunwindow/attr.h \ sunwindow/notify.h \ sunwindow/pixwin.h \ sunwindow/win_cursor.h \ sys/dir.h \ sys/fcntl.h \ sys/ioctl.h \ sys/stat.h \ sys/vfs.h \ sys/wait.h \ sys/resource.h \ sys/ttychars.h \ sys/types.h \ sys/param.h sun-include-files: cd g++-include; \ rm -fr $(SUN_INCLUDE_SUBDIRS); \ mkdir $(SUN_INCLUDE_SUBDIRS); \ for file in $(SUN_INCLUDE_FILES); do \ cp /usr/include/$$file ./$$file; \ done; \ sh -x ../sun-incl-patches # Note that there is a problem if you use "diff -re". The problem is that if # there are sundirectories, the shell script which is produced fails to have # the whole (relative) pathname of the files to be edited in the "ed - " # command lines. Thus, we have to edit the patches file to put these full # relative pathnames in. This is done automagically below. sun-incl-patches: -rm -fr sun-include -mkdir sun-include cd sun-include; \ for DIR in $(SUN_INCLUDE_SUBDIRS); do \ mkdir $$DIR; \ done for FILE in $(SUN_INCLUDE_FILES); do \ ln g++-include/$$FILE sun-include/$$FILE; \ done -rm -f /tmp/sun-incl-patches /tmp/patches-patches ./sun-incl-patches -cd sun-include; \ diff -re /usr/include . > /tmp/sun-incl-patches -rm -fr sun-include touch /tmp/patches-patches for PATH in $(SUN_INCLUDE_FILES); do \ BASE=`/usr/bin/basename $$PATH`; \ echo 's%^ed - '$$BASE'%ed - '$$PATH'%' >> /tmp/patches-patches; \ done sed -f /tmp/patches-patches /tmp/sun-incl-patches > ./sun-incl-patches -rm -f /tmp/sun-incl-patches /tmp/patches-patches ln libg++/ChangeLog 644 473 0 62045 4677677672 6763 Wed Feb 28 05:27:15 1990 Doug Lea (dl at g.oswego.edu) * gperf: patches from schmidt * Makefiles: removed dependencies on /usr/include files Tue Feb 27 05:21:22 1990 Doug Lea (dl at g.oswego.edu) * Installed c++-mode.el update from detlefs Mon Feb 26 08:03:32 1990 Doug Lea (dl at g.oswego.edu) * Incremental.h now includes a default destructor to avoid linking problems. Thanks to eirik@elf.TN.Cornell.EDU. * all `error' routines now have const char*, not char* args. * Plex classes revamped to support const Plexes. Also, removed `changes', `changed', since they aren't necessary anymore Sat Feb 24 05:56:13 1990 Doug Lea (dl at g.oswego.edu) * File.h verbose_error_handler, et al now have const char*, not char* args * Installed EH2.cc in src Mon Feb 19 08:34:51 1990 Doug Lea (dl at g.oswego.edu) * installed Ngo's PlotFile3D in libg++/etc Sat Feb 17 05:28:25 1990 Doug Lea (dl at g.oswego.edu) * installed Schmidt's gperf, trie-gen, and Patricia revisions * String.cc pos <= 0 should be pos < 0 Tue Feb 13 08:21:11 1990 Doug Lea (dl at g.oswego.edu) * Itolong (Integer.cc) patch from salzman@rand.org Mon Feb 12 08:21:07 1990 Doug Lea (dl at g.oswego.edu) * allowed separate inclusion of ostream.h, istream.h and/or stream.h Thu Feb 8 07:02:49 1990 Doug Lea (dl at g.oswego.edu) * PlotFile: patches from ngo for Convex byte-ordering. Tue Feb 6 06:29:11 1990 Doug Lea (dl at g.oswego.edu) * Vec.ccP: sort() killed goto, replaced with nested if's, since g++ complains about binding contours. Sat Feb 3 08:30:06 1990 Doug Lea (dl at g.oswego.edu) * Getopt.h: opterr is public, not private * builtin.cc, Random.cc, streambuf.cc broken into little pieces * std.h getpgrp, setpgrp now have (...) signatures, since some versions on some systems have arguments. * put in malloc revision * prepend-header: globbing changes via ngo's patches * Plex: fixed declaration mismatches for fill Tue Jan 30 10:22:35 1990 Doug Lea (dl at g.oswego.edu) * kmp.cc: modified to use libg++ GetOpt, not libc getopt Wed Jan 24 05:47:53 1990 Doug Lea (dl at g.oswego.edu) * broke out struct xyzzy from builtin.cc into its own file in /src Sun Jan 21 09:44:10 1990 Doug Lea (dl at g.oswego.edu) * sys/types.h: protect wchar_t and ptrdiff_t from /usr/include version * stddef.h: wchar_t now defaults as unsigned short Sat Jan 20 08:51:01 1990 Doug Lea (dl at g.oswego.edu) * sys/file.h KERNEL now defined only if ultrix. Also a typo: file_f should be file_h Fri Jan 19 05:18:03 1990 Doug Lea (dl at g.oswego.edu) * malloc.c: added #ifndef NO_NEW_HANDLER, so malloc.c compilable in C environments with no new handlers, and other #ifdefs to make it C++-compilable as well. Tue Jan 16 04:54:27 1990 Doug Lea (dl at g.oswego.edu) * libg++-1.36.3 released. * etc/benchmarks: enabled various options, now that g++ works with them. * values.h vax MAX/MINFLOAT changed to be same as expected by gcc. * streambuf.cc: Filebuf::overflow(): Fp->eof() is not an error condition. * std.h, stdio.h: more extern C fns declared as returning int, not void when not specified as void by ANSI or C man pages. Sat Jan 13 13:41:29 1990 Doug Lea (dl at g.oswego.edu) * stdio.h: puts returns int Fri Jan 12 05:49:09 1990 Doug Lea (dl at g.oswego.edu) * etc/lf/Dirent.h closedir returns void on some system, so Dirent versions do too. Wed Jan 10 10:01:15 1990 Doug Lea (dl at g.oswego.edu) * Rational.h: 175 typo Mon Jan 8 09:43:14 1990 Doug Lea (dl at g.oswego.edu) * file.h: more protection against getting bad fn declarations from /usr/include * builtin.cc: removed dependency on float.h * String.h Join, replicate need to be friends Sat Jan 6 08:48:18 1990 Doug Lea (dl at g.oswego.edu) * from rfg: minor DGUX accomodations in std.h, stdio.h, math.h Fri Jan 5 06:41:02 1990 Doug Lea (dl at g.oswego.edu) * from Widen: added warning about tCurses needing linefeeds on broken libcurses, fixed misc typos, added cfree() to malloc.c * math.h -- added inline defs of isnan and isinf for sequents Wed Jan 3 08:29:43 1990 Doug Lea (dl at g.oswego.edu) * builtin.cc: Deleted global _libgxx_io_oblast: no longer needed killed extern decls of it elsewhere. * Strings, Integers: finished/cleaned up previous changes Tue Jan 2 10:43:29 1990 Doug Lea (dl at g.oswego.edu) * Integer.cc: isolated copy and clear calls to allocation fns * Strings: Removed StrTmp class, added double concatenation Mon Dec 11 08:31:48 1989 Doug Lea (dl at g.oswego.edu) * AVLSet.cc op &= plugged little memory leak: when u is exhausted, but t isn't, delete rest of t. * AVLMap: _delete: cont field wasn't copied in a case it should have been * merged tSet2 back into tSet and tBag2 back into tBag * BitSet.cc (BitSetCompl) ensure all 1's in s[0] when complementing empty set * builtin.cc (return_elapsd_time, set_timer) No longer #ifdef'ed for machines -- new .h organization should work for all. * builtin.cc (lg) redeclared as unsigned->long * DGUX patches from rfg installed Tue Dec 5 11:58:51 1989 Doug Lea (dl at g.oswego.edu) * BitSet, Integer, Rational: added constness, removed Tmp classes, and used named return values Sat Dec 2 06:21:12 1989 Doug Lea (dl at g.oswego.edu) * builtin.cc (dtoa) #if _IEEE != 0 handle isnan, isinf * builtin.cc (itoa) force unsigned division in case num == MININT Fri Dec 1 10:08:21 1989 Doug Lea (dl at g.oswego.edu) * istream::operator>> clear eof if at eof but got something valid * String::match and Regex::match return -1 on failure, since 0 could be a legal value * gnulib3.c: Commented out ON_EXIT stuff. On Suns, for some reason, on_exit routines don't link into libraries right. * std.h: fixed getopt proto * stat.h : added fn protos * installed Schmidt's reorganization of etc * math-68881.h fix paren error noted on bug-gcc list * CursesWindow(WINDOW*) initialize sib * Renamed AllocQueue to AllocRing * test.hello.cc #ifdefs for MIPSEL * Plex::del_chunk() delete the chunk, not just the chunk's data Sat Nov 25 12:50:06 1989 Doug Lea (dl at g.oswego.edu) * VStack, VQueue: add operator =() * Obstack::Obstack don't allocate on constructor, just on first use * String::_gsub: don't build new rep if no matches * builtin.h: added more versions of abs * installed new malloc, and new.{h, cc} Thu Nov 23 06:20:17 1989 Doug Lea (dl at g.oswego.edu) * added Schmidt's g++dep to etc * math.h: additions for anint(), etc., HP HAVE_FPU Wed Nov 22 14:48:24 1989 Doug Lea (dl at g.oswego.edu) * Added Schmidt's trie-gen to libg++/etc Tue Nov 21 08:50:47 1989 Doug Lea (dl at g.oswego.edu) * streambuf: eptr is now the pointer to the last valid char in buffer, not the fence pointer, for AT&T compatibilty * stream, streambuf : Added line buffered put's as default must #define NO_LINE_BUFFER_STREAMBUF to override Mon Nov 20 09:52:47 1989 Doug Lea (dl at g.oswego.edu) * Plex: finish previous change: add_low, add_high don't introduce straggling chunks * new.h: typo, plus add default placement version of new() * PlotFile, BitString, Fix16 .h's: more cfrontisms Sun Nov 19 07:38:36 1989 Doug Lea (dl at g.oswego.edu) * removed File::operator FILE*() because it can lead to ambiguities. * incorporated cfront-dependent #ifdefs, etc. from Schmidt * Fix24: integrated patches from wang Sat Nov 18 07:17:04 1989 Doug Lea (dl at g.oswego.edu) * XPlex, RPlex, MPlex (del_low, del_high) old straggling empty chunks weren't being deleted. fixed. Thu Nov 16 05:56:43 1989 Doug Lea (dl at g.oswego.edu) * resource.h: added getrlimit, setrlimit Wed Nov 15 05:54:46 1989 Doug Lea (dl at g.oswego.edu) * String.h: typo const& Regex => const Regex& Fri Nov 10 06:45:55 1989 Doug Lea (dl at g.oswego.edu) * Makefile: force submakes in non-gnumake fashion Thu Nov 9 09:32:21 1989 Doug Lea (dl at g.oswego.edu) * Curses.cc, curses.h, ctype.h: patches based on darrlyo's stuff. * Fix.cc : *Correctly* installed ++i patch! Wed Nov 8 06:19:39 1989 Doug Lea (dl at g.oswego.edu) * stdio.h now is now sub-included in other .h's needing USG-based info. * new etc/c++-mode.el from detlefs * etc/Makefile: -DETAGS for etags.c * more HPUX patches from darrylo and mike fion Tue Nov 7 07:23:25 1989 Doug Lea (dl at g.oswego.edu) * Fix.{h, cc}: cleanup in search of memory leaks * Added -DNO_GNULIB3 option in top-level Makefile Mon Nov 6 05:53:42 1989 Doug Lea (dl at g.oswego.edu) * std.h, stdio.h, ctype.h.... HPUX and DGUX patches from cole & darrylo * tests/Makefile tCurses taken out of checktests * Bitset.cc: fixed underallocation in BitSettoa according to patch from darrylo@hpsrdmo.hp.com Sun Nov 5 06:45:26 1989 Doug Lea (dl at g.oswego.edu) * gnulib3, Incremental.h, test.hello.cc: patched via Eirik Fuller's incremental loading fixes Fri Nov 3 11:22:39 1989 Doug Lea (dl at g.oswego.edu) * 1.36.0 released, after misc cleanup Tue Oct 31 09:44:32 1989 Doug Lea (dl at g.oswego.edu) * added Rich Murphey's graph program to libg++/etc Mon Oct 30 10:13:07 1989 Doug Lea (dl at g.oswego.edu) * sys/file.h: include types.h & maybe fcntl.h Some folks need them * std.h: index, bcopy, etc. now inline, not macro if USG * streambuf.h: sputback returns success; stream.h istream::putback/unget: set(_fail) if bad Tue Oct 24 16:53:05 1989 Doug Lea (dl at g.oswego.edu) * stddef.h -- now really defines size_t. OK via new sys/types.h fake-out. * time.h -- now includes //usr/include/time.h too Sun Oct 22 07:58:36 1989 Doug Lea (dl at g.oswego.edu) * String.h, cc: reworked to allow proper operation for consts (some new stuff #ifdef'ed out because of g++ problems) Sat Oct 21 15:29:55 1989 Doug Lea (dl at g.oswego.edu) * Fix.cc: (new_Fix) cure for d < 0 problem from eirik fuller * builtin.cc: added dtoa * AllocQueue.h,cc: added it & use elsewhere for building formatting & ascii conversions Wed Oct 18 05:37:11 1989 Doug Lea (dl at g.oswego.edu) * Fix16.cc, Fix24.cc: Fixed operator / per wang's suggestions Tue Oct 17 06:47:25 1989 Doug Lea (dl at g.oswego.edu) * stream.cc, Integer.cc: istream op >>, fixed to not read after EOF when decoding numbers Mon Oct 16 15:33:11 1989 Doug Lea (dl at g.oswego.edu) * added ostream << long long, and itoa's to handle * values.h, stdio.h, Fix.cc, File.cc: things for convex from convex!csmith@uxc.cso.uiuc.edu Sat Oct 14 07:19:30 1989 Doug Lea (dl at g.oswego.edu) * time.h: typedef'ed timezone to c_proto_timezone if not USG Wed Oct 11 09:42:39 1989 Doug Lea (dl at g.oswego.edu) * Makefiles: fixed various typos * misc: cleaned up enum clashes reported with -Wenum-clash * stream.cc Added #ifdefs to use filebufs for standard streams if Filebufs give people trouble. Tue Oct 3 07:02:56 1989 Doug Lea (dl at g.oswego.edu) * setjmp.h: now #includes host /usr/include/setjmp.h Mon Oct 2 16:00:59 1989 Doug Lea (dl at g.oswego.edu) * commented out gcc constness in revised Complex.h since it's still officially illegal to declare fns with refs(ptrs) as const * incorporated new gperf from schmidt * added dhrystone benchmark to etc Sat Sep 30 09:02:07 1989 Doug Lea (dl at g.oswego.edu) * Complex.h: revamped to use const, etc. Fri Sep 29 06:58:56 1989 Doug Lea (dl at g.oswego.edu) * added src/EH.cc from tiemann * SLList.hP now #include's the .defs file * CHSet, CHBag, CHMap, VHSet, VHBag, VHMap -- changed ints to unsigned ints to ensure unsigned operations throughout. Mon Sep 25 07:32:11 1989 Doug Lea (dl at g.oswego.edu) * added new.h Sun Sep 24 05:31:50 1989 Doug Lea (dl at g.oswego.edu) * tgwrapper.cc: added init_nil to avoid crashes on exit. * other miscellaneous cleanup (fixed enum/int clashes, etc.) to adapt to latest g++-1.36.0- * bool enum now in bool.h Thu Sep 14 06:18:46 1989 Doug Lea (dl at g.oswego.edu) * sys/socket.h: select must have void* args, since different systems use int* or fd_set* Wed Sep 13 11:38:19 1989 Doug Lea (dl at g.oswego.edu) * builtin.cc: added unsigned versions of itoa, hex, dec, oct Tue Sep 12 09:28:01 1989 Doug Lea (dl at g.oswego.edu) * more misc. cleanup to avoid warnings: removed redundant type information from declarations of all coercion operators. Sat Sep 9 06:25:03 1989 Doug Lea (dl at g.oswego.edu) * (everywhere) miscellaneous aesthetic cleanup to minimize g++ warning messages. * (lots of files) used 'virtual fn() = 0' for pure virtual functions, removing old `error(unimplemented...)' constructs. allowed deletion of Stack.ccP, Queue.ccP, Deque.ccP files which did only this. * took all defines out of libconfig.h, and killed it HAVE_VPRINTF, etc -> stdio.h CHAR_PER_LONG, etc -> Integer.cc SHOULD_FREE_TO_REALLOC -> (no longer needed, killed) USG -> people should run g++ with -DUSG now Fri Sep 8 06:48:58 1989 Doug Lea (dl at g.oswego.edu) * added Clark's version of etags that handles c++, to etc/ * moved special sparc alloca decl from libconfig.h to std.h * std.h, math.h, ... killed `overload' declarations * etc/getopt* => src/GetOpt.cc, g++-include/GetOpt.h, with various corresponding changes Wed Sep 6 09:15:50 1989 Doug Lea (dl at g.oswego.edu) * math.h renamed `struct exception' to `libm_exception' * regex.c converted to use prototypes, etc. from schmidt Tue Sep 5 06:43:37 1989 Doug Lea (dl at g.oswego.edu) * new c++-mode.el from detlefs * added sys/param.h, which #undefs common macros, but keeps needed constants * Integer.h: rearranged ordering of some inlines to please g++ * Fix.h: need new constructor Fix(int, _Frep*) to please g++ * added __xyzzy hack from tiemann to builtin.cc * added gnulib3 from tiemann Thu Aug 31 07:36:42 1989 Doug Lea (dl at g.oswego.edu) * more USG stuff from Klossner (stdio.h, libconfig.h, values.h, ctype.h) Sun Aug 27 08:30:15 1989 Doug Lea (dl at g.oswego.edu) * genclass: changed to take output filename prefix argument to avoid long file names on SYSV; tests files change accordingly * installed gperf update from schmidt * tests: added runtests, checktests to Makefile. Some tests modified to suit. Sat Aug 26 09:00:14 1989 Doug Lea (dl at g.oswego.edu) * Plex, PHPQ files: deleted const qualifiers for some params as temporary measure until all containers revised to use const qualifiers as needed. * curses.h macros converted into inlines * added RankedAVLMap, based on code from paul%lfcs.ed.ac.uk * moved non-ANSI stuff (TRUE, etc., ) from stddef.h to builtin.h * added more USG stuff sent from rfg, grandi, cole, to standard headers * std.h: added #ifdef USG section for USG->BSD conversions * Makefiles: made more things adjustable, better USG support * PHPQ.ccP: (preallocate) added missing size argument to vector delete Fri Aug 25 12:25:12 1989 Doug Lea (dl at g.oswego.edu) * streambuf.cc: dumb error in filebuf::overflow Thu Aug 24 11:46:16 1989 Doug Lea (dl at g.oswego.edu) * libconfig.h, values.h: #defines for sony from jkp Wed Aug 23 06:54:43 1989 Doug Lea (dl at g.oswego.edu) * Fix16.h, Fix32.h: declared op* as friends correctly * String.h: declared StrTmp op + as friends of String Mon Aug 21 07:02:53 1989 Doug Lea (dl at g.oswego.edu) * Poisson.h, Lognormal.h: add missing `public' * assert.h: abort() declared volatile * Vec.ccP: made gsort static * std.h: added rewind & bsearch * Makefiles: deleted -fchar-charconst Thu Aug 10 07:31:37 1989 Doug Lea (dl at g.oswego.edu) * builtin.{h, cc}: added str(const char*, int width = 0) * streambuf.cc: init_streambuf_ptrs: postpone action if fp->_cnt 0 (apparently needed for some USG systems) * stream.cc: get, getline: match AT&T 1.2 _fail conditions Sun Aug 6 07:16:19 1989 Doug Lea (dl at g.oswego.edu) * stream.cc, File.cc get(char[], int, char) read too many chars Thu Jul 20 09:42:44 1989 Doug Lea (dl at g.oswego.edu) * adapted more C-compatibility .h files from Interviews Wed Jul 19 09:23:27 1989 Doug Lea (dl at g.oswego.edu) * installed more C-compatibilty files: pwd.h, grp.h time.h Mon Jul 17 07:37:35 1989 Doug Lea (dl at g.oswego.edu) * installed Interviews/et++ compatible (I hope) signal.h * installed new version of gperf from schmidt * std.h: declared abort() and exit() as volatile * builtin.cc: typo in gcd * math.h: added overload decl for atan, etc * VHMap.cc: removed assumption that operator = returns value. * Makefiles: default dir is /usr/gnu/... not /usr/local * setjmp.h: fixed constants for sun to match those in sun /usr/include files, added ns32000 * BSTSet.ccP added new linear-time rebalancing algorithm * builtin.cc: SYSV versions of timing stuff from ron cole * File.{h,cc} fixed File::tell, added O_CREAT to exclusive access open, added fill(), flush(char). * incorporated new streams: stream.{h,cc}, streambuf.{h, cc}, libg++.texinfo Sat May 20 07:42:11 1989 Doug Lea (dl at rocky.oswego.edu) * math.h,math-68881.h: incorporated Fyfe's fixes to extern "C" problems Tue May 16 05:52:33 1989 Doug Lea (dl at rocky.oswego.edu) * RNG.cc ifdef _IEEE_ fixed to if _IEEE == 1 * Installed Staelin's prototype Makefile updates Mon May 15 06:25:12 1989 Doug Lea (dl at rocky.oswego.edu) * BitString.h: g++ optimizer bug workaround in left_trim * math-68881.h - fgetman (not fgetmant) fix from widen Sat May 13 11:00:35 1989 Doug Lea (dl at rocky.oswego.edu) * changes from tiemann for constructs of form X::f() changed to this->X::f(), necessary now that static members are implemented. [postscript: no, it wasn't necessary] * libg++.texinfo: misc documentation updates Fri May 12 05:06:06 1989 Doug Lea (dl at rocky.oswego.edu) * (lots of places) added friends and other minor changes to adapt to new ``correct'' (but losing) g++ interpretation of `protected:' * re-inserted `overload' in .h files -- tiemann says that gdb needs these for now * stream.cc: eatwhite was inline by mistake. fixed. Thu May 11 07:31:06 1989 Doug Lea (dl at rocky.oswego.edu) * List.ccP: initializer class for Nil, since can't always use { ... } initializer. Also made `head' a synonym for `get', per request. * installed changes to etc files from schmidt * String.cc Scopy: return &NilSrep, not 0 for null * added math-68881.h to g++-include (from grunwald) Sun May 7 08:38:10 1989 Doug Lea (dl at rocky.oswego.edu) * catch-up day!: converted header files to use extern "C" and #pragma once killed `overload' declarations everywhere renamed test files added the beginnings of SYSV (USG) support included some useful stuff for Suns in top Makefile (from Guilmette) cleaned up other Makefiles added File::gets (from Schmidt) moved gperf from etc to a top level subdir added the useless char* chr(ch) to builtin.h genclass puts dots in file names to use Staelins GNU Makefile stuff (also added his `prepend-header' utility) added Schmidt's getopt stuff into etc. New versions of fixpoint classes from Baudendistel (needed to change set_overflow_handler to set_{FixXX}_overflow_handler for each FixXX, since overloads clash on typedef'ed fn types) Adapted Schmidt's new quicksort for Vec class Fri Apr 28 16:26:17 1989 Doug Lea (dl at rocky.oswego.edu) * ACG.cc: fixed ~ACG per grunwald Thu Apr 20 05:22:46 1989 Doug Lea (dl at rocky.oswego.edu) * List.hP: first for nil list now returns null Pix * Integer.cc: rshift fixed problem with 0 shifts Mon Apr 10 05:17:04 1989 Doug Lea (dl at rocky.oswego.edu) * stream.h, PlotFile.h added explicit `private' for subclasses Sat Mar 18 06:08:30 1989 Doug Lea (dl at rocky.oswego.edu) * String.[h,cc]: added Regex::match_info Fri Mar 17 14:37:12 1989 Doug Lea (dl at rocky.oswego.edu) * stream.h: istream >> char now eats whitespace. * builtin.h: overloaded `even', `odd' Thu Mar 9 06:43:43 1989 Doug Lea (dl at rocky.oswego.edu) * Map.ccP: typo in Map::contents => * stdio.h : inserted coercion in putc macro to avoid incorrect sign extension. Tue Mar 7 05:35:52 1989 Doug Lea (dl at rocky.oswego.edu) * List.hP: List::push no longer incorrectly calls dereference * Inserted patches to etc stuff from Doug Schmidt Sun Mar 5 07:57:01 1989 Doug Lea (dl at rocky.oswego.edu) * stream.h: added File::check_state to public functions * BitSet.cc: longtoBitSet: Fixed typo Sat Mar 4 10:06:24 1989 Doug Lea (dl at rocky.oswego.edu) * installed CursesWindow files * miscellaneous corrections to test files in light of g++-1.34 changes Fri Mar 3 06:07:37 1989 Doug Lea (dl at rocky.oswego.edu) * incorporated new version of Doug Schmidt's gperf * BitString.cc: fixed reverse searching Sun Feb 26 05:44:28 1989 Doug Lea (dl at rocky.oswego.edu) * assert : killed old assert.cc, adapted gcc assert.h Sat Feb 25 09:23:35 1989 Doug Lea (dl at rocky.oswego.edu) * tests, libg++.texinfo: miscellaneous updates * stddef.h NULL is now just `0', not (void*)0 * Makefile: added `prefix' as in g++ Makefile * put a new c++-mode.el from david detlefs in etc * BitString.[h,cc] BitSet[h,cc] now use unsigned short arrays instead of unsigned longs to avoid long i; i >> 32, which does not work on Sun4s and probably other machines. Simplified a few shift & mask constructs accordingly. * values.h, libconfig.h: support for sequent from Johan Widen * Fix.h: repaired type mismatches * String.[cc,h] gsub now returns number of matches * String.cc gsub(Regex...): repaired using patches from kadmon!jason@mtxinu.com * stream.h scan didn't return *this if fail -- fixed. * File.cc get(char*...): get of an empty line not a _fail condition * RNG.[h,cc] installed new code from grunwald Tue Feb 7 05:53:23 1989 Doug Lea (dl at rocky.oswego.edu) * Integer.h,cc Added optional base to atoI via code from per bothner * String.h,cc Added `freq' method in String to count occurrences using code from john willis Mon Feb 6 07:25:06 1989 Doug Lea (dl at rocky.oswego.edu) * BitSet.cc:op <=, < now work if first arg shorter than second; clear() fixed. * stream.h, stream.cc: made ostream<<(char*) non-inline Sun Feb 5 05:31:36 1989 Doug Lea (dl at rocky.oswego.edu) * test19.cc: typo c.empty fixed to c.empty() Tue Jan 31 05:51:36 1989 Doug Lea (dl at rocky.oswego.edu) * String.h: contains(Regex) return fact that search returns >= 0, not just raw result. * Fix.h: correct protection problem in op* * replace regex.c with emacs 18.52 version Fri Jan 27 06:29:20 1989 Doug Lea (dl at rocky.oswego.edu) * AVLSet.ccP, AVLMap.ccP - check to see if root is null before trying to delete elements * libg++/Makefile - change install of libg++ to cd to src Sat Jan 14 06:03:33 1989 Doug Lea (dl at rocky.oswego.edu) * fixed info node pointers in libg++.texinfo Wed Jan 11 06:20:37 1989 Doug Lea (dl at rocky.oswego.edu) * libg++-1.32.0 released * Starting to use ChangeLog as of today 18.52 version Fri Jan 27 06:29:20 1989 Doug Lea (dl at rocky.oswego.edu) * AVLSet.ccP, AVLMap.ccP - check to see if root is null before trying to delete elements * libg++/Makefile - change install of libg++ to cd to src Sat Jan 14 06:03:33 1989 Doug Lea (dl at rocky.oswego.edu) * fixed info node pointers in libg++.texinfo Wed Jan 11 06:20:37 1989 Doug Lea (dl at rocky.oswego.edu) * libg++-1.32.0 released * Stlibg++/gperf/COPYING 644 473 0 30310 4677677673 7336 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 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 license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our 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. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 a 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 tell them 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. 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 Agreement 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 work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 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 General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual 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 General Public License. d) 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. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying 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. 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. 7. 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 the 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 the license, you may choose any version ever published by the Free Software Foundation. 8. 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 9. 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. 10. 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 humanity, 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. Copyright (C) 19yy 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 1, 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) 19xx 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 a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! 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 a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the programlibg++/gperf/README 644 473 0 1674 4677677673 7156 While teaching a data structures course at University of California, Irvine, I developed a program called GPERF that generates perfect hash functions for sets of key words. A perfect hash function is simply: A hash function and a data structure that allows recognition of a key word in a set of words using exactly 1 probe into the data structure. The gperf.texinfo file explains how the program works, the form of the input, what options are available, and hints on choosing the best options for particular key word sets. The texinfo file is readable both via the GNU emacs `info' command, and is also suitable for typesetting with TeX. The enclosed Makefile creates the executable program ``gperf'' and also runs some tests. Output from the GPERF program is used to recognize reserved words in the GNU C, GNU C++, and GNU Pascal compilers, as well as with the GNU indent program. Happy hacking! Douglas C. Schmidt rm of the input, what options are available, and hints on choosing tlibg++/gperf/src/bool-array.cc 644 473 0 4636 4677677673 11444 /* Fast lookup table abstraction implemented as an Iteration Number Array Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "options.h" #include "bool-array.h" /* Prints out debugging diagnostics. */ Bool_Array::~Bool_Array (void) { if (option[DEBUG]) fprintf (stderr, "\ndumping boolean array information\n" "size = %d\niteration number = %d\nend of array dump\n", size, iteration_number); } #ifndef __OPTIMIZE__ Bool_Array::Bool_Array (void) { storage_array = 0; iteration_number = size = 0; } void Bool_Array::init (STORAGE_TYPE *buffer, STORAGE_TYPE s) { size = s; iteration_number = 1; storage_array = buffer; bzero (storage_array, s * sizeof *storage_array); if (option[DEBUG]) fprintf (stderr, "\nbool array size = %d, total bytes = %d\n", size, size * sizeof *storage_array); } int Bool_Array::find (int index) { if (storage_array[index] == iteration_number) return 1; else { storage_array[index] = iteration_number; return 0; } } void Bool_Array::reset (void) { /* If we wrap around it's time to zero things out again! However, this only occurs once about every 2^31 or 2^15 iterations, so it should probably never happen! */ if (++iteration_number == 0) { if (option[DEBUG]) { fprintf (stderr, "(re-initializing bool_array)..."); fflush (stderr); } iteration_number = 1; bzero (storage_array, size * sizeof *storage_array); if (option[DEBUG]) { fprintf (stderr, "done\n"); fflush (stderr); } } } #endif /* not defined __OPTIMIZE__ */ occurs once about every 2^31 or 2^15 iterations, so it should probably never happen! */ libg++/gperf/src/vectors.h 644 473 0 2254 4677677673 10716 /* This may look like C code, but it is really -*- C++ -*- */ /* Static class data members that are shared between several classes via inheritance. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once struct Vectors { const int ALPHA_SIZE = 128; static int occurrences[ALPHA_SIZE]; /* Counts occurrences of each key set character. */ static int asso_values[ALPHA_SIZE]; /* Value associated with each character. */ }; R PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once struct Vectors { const int ALPHA_SIZE = 128; statilibg++/gperf/src/hash-table.cc 644 473 0 6054 4677677674 11402 /* Hash table for checking keyword links. Implemented using double hashing. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "hash-table.h" #include "options.h" /* Find out how well our double hashing is working! */ static collisions = 0; #define NIL(TYPE) (TYPE *)0 /* The size of the hash table is always the smallest power of 2 >= the size indicated by the user. This allows several optimizations, including the use of double hashing and elimination of the mod instruction. Note that the size had better be larger than the number of items in the hash table, else there's trouble!!! Note that the memory for the hash table is allocated *outside* the intialization routine. This compromises information hiding somewhat, but greatly reduces memory fragmentation, since we can now use alloca! */ Hash_Table::Hash_Table (List_Node **table_ptr, int s) { size = s; table = table_ptr; bzero ((char *) table, size * sizeof *table); } Hash_Table::~Hash_Table (void) { if (option[DEBUG]) { int field_width = option.get_max_keysig_size (); fprintf (stderr, "\ndumping the hash table\ntotal entries = %d, total bytes = %d\n" "location, %*s, keyword\n", size, size * sizeof *table, field_width, "keysig"); for (int i = size - 1; i >= 0; i--) if (table[i]) fprintf (stderr, "%8d, %*s, %s\n", i, field_width, table[i]->char_set, table[i]->key); fprintf (stderr, "\ntotal collisions during hashing = %d\nend dumping hash table\n\n", collisions); } } /* If the ITEM is already in the hash table return the item found in the table. Otherwise inserts the ITEM, and returns FALSE. Uses double hashing. */ List_Node * Hash_Table::operator () (List_Node *item, int ignore_length) { unsigned hash_val = hashpjw (item->char_set); int probe = hash_val & size - 1; int increment = (hash_val ^ item->length | 1) & size - 1; while (table[probe] && (strcmp (table[probe]->char_set, item->char_set) || (!ignore_length && table[probe]->length != item->length))) { collisions++; probe = probe + increment & size - 1; } return table[probe] ? /* Elided! */ : (table[probe] = item, NIL (List_Node)); } de *item, int ignore_length) { unsigned hash_val = hashpjw (item->char_set); int probe = hash_val & size - 1; int increment = (hash_val ^ item->length | 1) & size - 1; while (table[probe] && (strcmp (table[probe]->char_set, item->char_set) || (!ignore_length && table[probe]->length != item->length))) { collisions++; probe = probe + increment & size - 1; } return table[probe] ? /* Elided! */ : libg++/gperf/src/version.cc 644 473 0 1564 4677677674 11060 /* Current program version number. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ char *version_string = "2.3 (GNU C++ version)"; option) any later version. GNU GPERF is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the impliedlibg++/gperf/src/key-list.h 644 473 0 11252 4677677674 11011 /* This may look like C code, but it is really -*- C++ -*- */ /* Data and function member declarations for the keyword list class. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* The key word list is a useful abstraction that keeps track of various pieces of information that enable that fast generation of the Gen_Perf.hash function. A Key_List is a singly-linked list of List_Nodes. */ #pragma once #include "list-node.h" #include "std-err.h" #include "vectors.h" #include "read-line.h" class Key_List : private Std_Err, private Read_Line, public Vectors { private: const int MAX_INT = ~unsigned (0) >> 1; /* Most positive integer value. */ const int NEG_MAX_INT = ~unsigned (0) ^ MAX_INT; /* Most negative integer value. */ const int MAX_UNSIGNED_CHAR = 255; /* Maximum value an unsigned char can take. */ const int MAX_UNSIGNED_SHORT = 65535; /* Maximum value an unsigned short can take. */ const int MIN_SIGNED_SHORT = -32768; /* Minimum value a signed short can take. */ const int TABLE_MULTIPLE = 5; /* Make the hash table 5 times larger than the number of keyword entries. */ char *const default_array_type = "char *"; /* Default type for generated code. */ char *const default_return_type = "char *"; /* in_word_set return type, by default. */ char *array_type; /* Pointer to the type for word list. */ char *return_type; /* Pointer to return type for lookup function. */ char *struct_tag; /* Shorthand for user-defined struct tag type. */ char *include_src; /* C source code to be included verbatim. */ int max_key_len; /* Maximum length of the longest keyword. */ int min_key_len; /* Minimum length of the shortest keyword. */ int min_hash_value; /* Minimum hash value for all keywords. */ int max_hash_value; /* Maximum hash value for all keywords. */ int occurrence_sort; /* True if sorting by occurrence. */ int hash_sort; /* True if sorting by hash value. */ int additional_code; /* True if any additional C code is included. */ int list_len; /* Length of head's Key_List, not counting duplicates. */ int total_keys; /* Total number of keys, counting duplicates. */ static int determined[ALPHA_SIZE]; /* Used in function reorder, below. */ static int get_occurrence (List_Node *ptr); static int strcspn (const char *s, const char *reject); static int already_determined (List_Node *ptr); static void set_determined (List_Node *ptr); void output_min_max (void); void output_switch (void); void output_keyword_table (void); void output_keylength_table (void); void output_hash_function (void); void output_lookup_function (void); void output_lookup_array (void); void set_output_types (void); void dump (void); char *get_array_type (void); char *save_include_src (void); char *get_special_input (char delimiter); List_Node *merge (List_Node *list1, List_Node *list2); List_Node *merge_sort (List_Node *head); protected: List_Node *head; /* Points to the head of the linked list. */ int total_duplicates; /* Total number of duplicate hash values. */ public: Key_List (void); ~Key_List (void); int keyword_list_length (void); int max_key_length (void); void reorder (void); void sort (void); void read_keys (void); void output (void); }; erge_sort (List_Node *head); protected: List_Node *head; /* Points to the head of the linked list. */ int total_duplicates; /* Total number of duplicate hash values. */ public: Key_List (void); ~Key_List (void); int keyword_list_lenlibg++/gperf/src/read-line.cc 644 473 0 3734 4677677674 11234 /* Correctly reads an arbitrarily size string. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "std-err.h" #include "read-line.h" /* Recursively fills up the buffer. */ char * Read_Line::readln_aux(int chunks) { char buf[CHUNK_SIZE]; char *bufptr = buf; char *ptr; int c; while ((c = getc (fp)) != EOF && c != '\n') /* fill the current buffer */ { *bufptr++ = c; if (bufptr - buf >= CHUNK_SIZE) /* prepend remainder to ptr buffer */ { if (ptr = readln_aux (chunks + 1)) for (; bufptr != buf; *--ptr = *--bufptr); return ptr; } } if (c == EOF && bufptr == buf) return 0; c = chunks * CHUNK_SIZE + bufptr - buf + 1; ptr = new char[c]; for (*(ptr += (c - 1)) = '\0'; bufptr != buf; *--ptr = *--bufptr) ; return ptr; } #ifndef __OPTIMIZE__ /* Returns the ``next'' line, ignoring comments beginning with '#'. */ char * Read_Line::get_line (void) { int c; if ((c = getc (fp)) == '#') { while ((c = getc (fp)) != '\n' && c != EOF) ; return c != EOF ? get_line () : 0; } else { ungetc (c, stdin); return readln_aux (0); } } /* Returns length of ``current'' line. */ #endif char[c]; for (*(ptr += (c - 1)) =libg++/gperf/src/iterator.cc 644 473 0 4610 4677677674 11217 /* Provides an Iterator for keyword characters. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "iterator.h" /* Constructor for Iterator. */ Iterator::Iterator (char *s, int lo, int hi, int word_end, int bad_val, int key_end) { end = key_end; error_value = bad_val; end_word = word_end; str = s; hi_bound = hi; lo_bound = lo; } /* Provide an Iterator, returning the ``next'' value from the list of valid values given in the constructor. */ int Iterator::operator () (void) { /* Variables to record the Iterator's status when handling ranges, e.g., 3-12. */ static int size; static int curr_value; static int upper_bound; if (size) { if (++curr_value >= upper_bound) size = 0; return curr_value; } else { while (*str) switch (*str) { default: return error_value; case ',': str++; break; case '$': str++; return end_word; case '1'..'9': for (curr_value = 0; isdigit (*str); str++) curr_value = curr_value * 10 + *str - '0'; if (*str == '-') { for (size = 1, upper_bound = 0; isdigit (*++str); upper_bound = upper_bound * 10 + *str - '0'); if (upper_bound <= curr_value || upper_bound > hi_bound) return error_value; } return curr_value >= lo_bound && curr_value <= hi_bound ? curr_value : error_value; } return end; } } urr_value * 10 + *str - '0'; if (*str == '-') { for (size = 1, upper_bound libg++/gperf/src/gen-perf.h 644 473 0 3333 4677677675 10735 /* This may look like C code, but it is really -*- C++ -*- */ /* Provides high-level routines to manipulate the keyword list structures the code generation output. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once #include "std-err.h" #include "key-list.h" #include "bool-array.h" class Gen_Perf : private Key_List, private Bool_Array { private: int max_hash_value; /* Maximum possible hash value. */ int fewest_collisions; /* Records fewest # of collisions for asso value. */ int num_done; /* Number of keywords processed without a collision. */ void change (List_Node *prior, List_Node *curr); int affects_prev (char c, List_Node *curr); static int hash (List_Node *key_node); static int compute_disjoint_union (char *set_1, char *set_2, char *set_3); static void sort_set (char *union_set, int len); public: Gen_Perf (void); ~Gen_Perf (void); int operator () (void); }; lisions for asso value. */ int num_done; /* Number of keywords processed without a collision. */ void change (List_Node *prior, List_Node *curr); int affects_prev (char c, List_Node *curr); static int hash (List_Node *key_node); static int computlibg++/gperf/src/bool-array.h 644 473 0 5443 4677677675 11305 /* This may look like C code, but it is really -*- C++ -*- */ /* Simple lookup table abstraction implemented as an Iteration Number Array. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Define and implement a simple boolean array abstraction, uses a Guilmette implementation to save on initialization time. */ #pragma once #include #ifdef LO_CAL /* If we are on a memory diet then we'll only make these use a limited amount of storage space. */ typedef unsigned short STORAGE_TYPE; #else typedef int STORAGE_TYPE; #endif class Bool_Array { private: static STORAGE_TYPE *storage_array; /* Initialization of the index space. */ static STORAGE_TYPE iteration_number; /* Keep track of the current iteration. */ static int size; /* Keep track of array size. */ public: Bool_Array (void); ~Bool_Array (void); static void init (STORAGE_TYPE *buffer, STORAGE_TYPE s); static int find (int hash_value); static void reset (void); }; #ifdef __OPTIMIZE__ /* efficiency hack! */ inline Bool_Array::Bool_Array (void) { storage_array = 0; iteration_number = size = 0; } inline void Bool_Array::init (STORAGE_TYPE *buffer, STORAGE_TYPE s) { size = s; iteration_number = 1; storage_array = buffer; bzero (storage_array, s * sizeof *storage_array); if (option[DEBUG]) fprintf (stderr, "\nbool array size = %d, total bytes = %d\n", size, size * sizeof *storage_array); } inline int Bool_Array::find (int index) { if (storage_array[index] == iteration_number) return 1; else { storage_array[index] = iteration_number; return 0; } } inline void Bool_Array::reset (void) { if (++iteration_number == 0) { if (option[DEBUG]) { fprintf (stderr, "(re-initializing bool_array)..."); fflush (stderr); } iteration_number = 1; bzero (storage_array, size * sizeof *storage_array); if (option[DEBUG]) { fprintf (stderr, "done\n"); fflush (stderr); } } } #endif else { storage_array[index] = iteration_number; return 0; } } inline void Bool_Array::reset (void) { if (++iteration_number == 0) { if (option[DEBUG]) { fprintf (stlibg++/gperf/src/options.h 644 473 0 22313 4677677675 10744 /* This may look like C code, but it is really -*- C++ -*- */ /* Handles parsing the Options provided to the user. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This module provides a uniform interface to the various options available to a user of the gperf hash function generator. In addition to the run-time options, found in the Option_Type below, there is also the hash table Size and the Keys to be used in the hashing. The overall design of this module was an experiment in using C++ classes as a mechanism to enhance centralization of option and and error handling, which tend to get out of hand in a C program. */ #pragma once #include "std-err.h" /* Enumerate the potential debugging Options. */ enum Option_Type { DEBUG = 01, /* Enable debugging (prints diagnostics to Std_Err). */ ORDER = 02, /* Apply ordering heuristic to speed-up search time. */ ANSI = 04, /* Generate ANSI prototypes. */ ALLCHARS = 010, /* Use all characters in hash function. */ GNU = 020, /* Assume GNU extensions (primarily function inline). */ TYPE = 040, /* Handle user-defined type structured keyword input. */ RANDOM = 0100, /* Randomly initialize the associated values table. */ DEFAULTCHARS = 0200, /* Make default char positions be 1,$ (end of keyword). */ SWITCH = 0400, /* Generate switch output to save space. */ POINTER = 01000, /* Have in_word_set function return pointer, not boolean. */ NOLENGTH = 02000, /* Don't include keyword length in hash computations. */ LENTABLE = 04000, /* Generate a length table for string comparison. */ DUP = 010000, /* Handle duplicate hash values for keywords. */ FAST = 020000, /* Generate the hash function ``fast.'' */ NOTYPE = 040000, /* Don't include user-defined type definition in output -- it's already defined elsewhere. */ COMP = 0100000, /* Generate strncmp rather than strcmp. */ GLOBAL = 0200000, /* Make the keyword table a global variable. */ CONST = 0400000, /* Make the generated tables readonly (const). */ CPLUSPLUS = 01000000, /* Generate C++ code. */ C = 02000000, /* Generate C code. */ }; /* Define some useful constants (these don't really belong here, but I'm not sure where else to put them!). These should be consts, but g++ doesn't seem to do the right thing with them at the moment... ;-( */ enum { MAX_KEY_POS = 128 - 1, /* Max size of each word's key set. */ WORD_START = 1, /* Signals the start of a word. */ WORD_END = 0, /* Signals the end of a word. */ EOS = MAX_KEY_POS, /* Signals end of the key list. */ }; /* Class manager for gperf program Options. */ class Options : private Std_Err { public: Options (void); ~Options (void); int operator[] (Option_Type option); void operator() (int argc, char *argv[]); void operator= (enum Option_Type); void operator!= (enum Option_Type); static void print_options (void); static void set_asso_max (int r); static int get_asso_max (void); static void reset (void); static int get (void); static int get_iterations (void); static int get_max_keysig_size (void); static void set_keysig_size (int); static int get_jump (void); static int initial_value (void); static int get_total_switches (void); static const char *get_function_name (void); static const char *get_key_name (void); static const char *get_class_name (void); static const char *get_hash_name (void); static const char *get_delimiter (void); private: const int DEFAULT_JUMP_VALUE = 5; /* Size to jump on a collision. */ const char *const DEFAULT_NAME = "in_word_set"; /* Default name for generated lookup function. */ const char *const DEFAULT_KEY = "name"; /* Default name for the key component. */ const char *const DEFAULT_CLASS_NAME = "Perfect_Hash"; /* Default name for the generated class. */ const char *const DEFAULT_HASH_NAME = "hash"; /* Default name for generated hash function. */ const char *const DEFAULT_DELIMITERS = ",\n"; /* Default delimiters that separate keywords from their attributes. */ static int option_word; /* Holds the user-specified Options. */ static int total_switches; /* Number of switch statements to generate. */ static int total_keysig_size; /* Total number of distinct key_positions. */ static int size; /* Range of the hash table. */ static int key_pos; /* Tracks current key position for Iterator. */ static int jump; /* Jump length when trying alternative values. */ static int initial_asso_value; /* Initial value for asso_values table. */ static int argument_count; /* Records count of command-line arguments. */ static int iterations; /* Amount to iterate when a collision occurs. */ static char **argument_vector; /* Stores a pointer to command-line vector. */ static const char *function_name; /* Names used for generated lookup function. */ static const char *key_name; /* Name used for keyword key. */ static const char *class_name; /* Name used for generated C++ class. */ static const char *hash_name; /* Name used for generated hash function. */ static const char *delimiters; /* Separates keywords from other attributes. */ static char key_positions[MAX_KEY_POS]; /* Contains user-specified key choices. */ static int key_sort (char *base, int len); /* Sorts key positions in REVERSE order. */ static void usage (void); /* Prints proper program usage. */ }; /* Global option coordinator for the entire program. */ extern Options option; #ifdef __OPTIMIZE__ inline int Options::operator[] (Option_Type option) /* True if option enable, else false. */ { return option_word & option; } inline void Options::operator = (enum Option_Type opt) /* Enables option OPT. */ { option_word |= opt; } inline void Options::operator != (enum Option_Type opt) /* Disables option OPT. */ { option_word &= ~opt; } inline void Options::reset (void) /* Initializes the key Iterator. */ { key_pos = 0; } inline int Options::get (void) /* Returns current key_position and advanced index. */ { return key_positions[key_pos++]; } inline void Options::set_asso_max (int r) /* Sets the size of the table size. */ { size = r; } inline int Options::get_asso_max (void) /* Returns the size of the table size. */ { return size; } inline int Options::get_max_keysig_size (void) /* Returns total distinct key positions. */ { return total_keysig_size; } inline void Options::set_keysig_size (int size) /* Sets total distinct key positions. */ { total_keysig_size = size; } inline int Options::get_jump (void) /* Returns the jump value. */ { return jump; } inline const char * Options::get_function_name (void) /* Returns the jump value. */ { return function_name; } inline const char * Options::get_key_name (void) /* Returns the keyword key name. */ { return key_name; } inline const char * Options::get_hash_name (void) /* Returns the hash function name. */ { return hash_name; } inline const char * Options::get_class_name (void) /* Returns the generated class name. */ { return class_name; } inline int Options::initial_value (void) /* Returns the initial associated character value. */ { return initial_asso_value; } inline int Options::get_iterations (void) /* Returns the iterations value. */ { return iterations; } inline const char * Options::get_delimiter () /* Returns the string used to delimit keywords from other attributes. */ { return delimiters; } inline int Options::get_total_switches () /* Gets the total number of switch statements to generate. */ { return total_switches; } #endif Options::initial_value (void) /* Returns the initial associated character value. */ { return initial_asso_value; } inline int Options::get_iterations (void) /* Returns the iterations value. */ { return iterations; } inline const char * Options::get_delimiter () /* Returns the string used to delimilibg++/gperf/src/options.cc 644 473 0 53741 4677677675 11113 /* Handles parsing the Options provided to the user. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "options.h" #include "iterator.h" /* Global option coordinator for the entire program. */ Options option; /* Current program version. */ extern char *version_string; /* Prints program usage to standard error stream. */ static inline void Options::usage (void) { report_error ("Usage: %n [-acCdDef[num]gGhHijkKlLnNoprsStTv].\n" "(type %n -h for help)\n"); } /* Output command-line Options. */ void Options::print_options (void) { int i; printf ("/* Command-line: "); for (i = 0; i < argument_count; i++) printf ("%s ", argument_vector[i]); printf (" */"); } /* Sorts the key positions *IN REVERSE ORDER!!* This makes further routines more efficient. Especially when generating code. Uses a simple Insertion Sort since the set is probably ordered. Returns 1 if there are no duplicates, 0 otherwise. */ static inline int Options::key_sort (char *base, int len) { int i, j; for (i = 0, j = len - 1; i < j; i++) { int curr, tmp; for (curr = i + 1,tmp = base[curr]; curr > 0 && tmp >= base[curr - 1]; curr--) if ((base[curr] = base[curr - 1]) == tmp) /* oh no, a duplicate!!! */ return 0; base[curr] = tmp; } return 1; } /* Sets the default Options. */ Options::Options (void) { key_positions[0] = WORD_START; key_positions[1] = WORD_END; key_positions[2] = EOS; total_keysig_size = 2; delimiters = DEFAULT_DELIMITERS; jump = DEFAULT_JUMP_VALUE; option_word = DEFAULTCHARS | C; function_name = DEFAULT_NAME; key_name = DEFAULT_KEY; hash_name = DEFAULT_HASH_NAME; class_name = DEFAULT_CLASS_NAME; total_switches = size = 1; initial_asso_value = iterations = 0; } /* Dumps option status when debug is set. */ Options::~Options (void) { if (option_word & DEBUG) { char *ptr; fprintf (stderr, "\ndumping Options:\nDEBUG is.......: %s\nORDER is.......: %s" "\nANSI is........: %s\nTYPE is........: %s\nGNU is.........: %s" "\nRANDOM is......: %s\nDEFAULTCHARS is: %s\nSWITCH is......: %s" "\nPOINTER is.....: %s\nNOLENGTH is....: %s\nLENTABLE is....: %s" "\nDUP is.........: %s\nFAST is........: %s\nCOMP is.....: %s" "\nNOTYPE is......: %s\nGLOBAL is......: %s\nCONST is....: %s" "\nCPLUSPLUS is...: %s\nC is...........: %s" "\niterations = %d\nlookup function name = %s\nhash function name = %s" "\nkey name = %s\njump value = %d\nmax associcated value = %d" "\ninitial associated value = %d\ndelimiters = %s\nnumber of switch statements = %d\n", option_word & DEBUG ? "enabled" : "disabled", option_word & ORDER ? "enabled" : "disabled", option_word & ANSI ? "enabled" : "disabled", option_word & TYPE ? "enabled" : "disabled", option_word & GNU ? "enabled" : "disabled", option_word & RANDOM ? "enabled" : "disabled", option_word & DEFAULTCHARS ? "enabled" : "disabled", option_word & SWITCH ? "enabled" : "disabled", option_word & POINTER ? "enabled" : "disabled", option_word & NOLENGTH ? "enabled" : "disabled", option_word & LENTABLE ? "enabled" : "disabled", option_word & DUP ? "enabled" : "disabled", option_word & FAST ? "enabled" : "disabled", option_word & COMP ? "enabled" : "disabled", option_word & NOTYPE ? "enabled" : "disabled", option_word & GLOBAL ? "enabled" : "disabled", option_word & CONST ? "enabled" : "disabled", option_word & CPLUSPLUS ? "enabled" : "disabled", option_word & C ? "enabled" : "disabled", iterations, function_name, hash_name, key_name, jump, size - 1, initial_asso_value, delimiters, total_switches); if (option_word & ALLCHARS) fprintf (stderr, "all characters are used in the hash function\n"); fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n", total_keysig_size); for (ptr = key_positions; *ptr != EOS; ptr++) if (*ptr == WORD_END) fprintf (stderr, "$\n"); else fprintf (stderr, "%d\n", *ptr); fprintf (stderr, "finished dumping Options\n"); } } /* Parses the command line Options and sets appropriate flags in option_word. */ void Options::operator () (int argc, char *argv[]) { GetOpt getopt (argc, argv, "adcCDe:f:gGhH:i:j:k:K:lL:nN:oprs:S:tTv"); int option_char; set_program_name (argv[0]); argument_count = argc; argument_vector = argv; while ((option_char = getopt ()) != EOF) { switch (option_char) { case 'a': /* Generated coded uses the ANSI prototype format. */ { option_word |= ANSI; break; } case 'c': /* Generate strncmp rather than strcmp. */ { option_word |= COMP; break; } case 'C': /* Make the generated tables readonly (const). */ { option_word |= CONST; break; } case 'd': /* Enable debugging option. */ { option_word |= DEBUG; report_error ("Starting program %n, version %s, with debuggin on.\n", version_string); break; } case 'D': /* Enable duplicate option. */ { option_word |= DUP; break; } case 'e': /* Allows user to provide keyword/attribute separator */ { option.delimiters = getopt.optarg; break; } case 'f': /* Generate the hash table ``fast.'' */ { option_word |= FAST; if ((iterations = atoi (getopt.optarg)) < 0) { report_error ("iterations value must not be negative, assuming 0\n"); iterations = 0; } break; } case 'g': /* Use the ``inline'' keyword for generated sub-routines. */ { option_word |= GNU; break; } case 'G': /* Make the keyword table a global variable. */ { option_word |= GLOBAL; break; } case 'h': /* Displays a list of helpful Options to the user. */ { report_error ( "-a\tGenerate ANSI standard C output code, i.e., function prototypes.\n" "-c\tGenerate comparison code using strncmp rather than strcmp.\n" "-C\tMake the contents of generated lookup tables constant, i.e., readonly.\n" "-d\tEnables the debugging option (produces verbose output to the standard error).\n" "-D\tHandle keywords that hash to duplicate values. This is useful\n" "\tfor certain highly redundant keyword sets. It enables the -S option.\n" "-e\tAllow user to provide a string containing delimiters used to separate\n" "\tkeywords from their attributes. Default is \",\\n\"\n" "-f\tGenerate the gen-perf.hash function ``fast.'' This decreases GPERF's\n" "\trunning time at the cost of minimizing generated table-size.\n" "\tThe numeric argument represents the number of times to iterate when\n" "\tresolving a collision. `0' means ``iterate by the number of keywords.''\n" "-g\tAssume a GNU compiler, e.g., g++ or gcc. This makes all generated\n" "\troutines use the ``inline'' keyword to remove cost of function calls.\n" "-G\tGenerate the static table of keywords as a static global variable,\n" "\trather than hiding it inside of the lookup function (which is the\n" "\tdefault behavior).\n" "-h\tPrints this mesage.\n" "-H\tAllow user to specify name of generated hash function. Default\n" "\tis `hash'.\n" "-i\tProvide an initial value for the associate values array. Default is 0.\n" "\tSetting this value larger helps inflate the size of the final table.\n" "-j\tAffects the ``jump value,'' i.e., how far to advance the associated\n" "\tcharacter value upon collisions. Must be an odd number, default is %d.\n" "-k\tAllows selection of the key positions used in the hash function.\n" "\tThe allowable choices range between 1-%d, inclusive. The positions\n" "\tare separated by commas, ranges may be used, and key positions may\n" "\toccur in any order. Also, the meta-character '*' causes the generated\n" "\thash function to consider ALL key positions, and $ indicates the\n" "\t``final character'' of a key, e.g., $,1,2,4,6-10.\n" "-K\tAllow use to select name of the keyword component in the keyword structure.\n" "-l\tCompare key lengths before trying a string comparison. This helps\n" "\tcut down on the number of string comparisons made during the lookup.\n" "-L\tGenerates code in the language specified by the option's argument. Languages\n" "\thandled are currently C++ and C. The default is C.\n" "-n\tDo not include the length of the keyword when computing the hash function\n" "-N\tAllow user to specify name of generated lookup function. Default\n" "\tname is `in_word_set.'\n" "-o\tReorders input keys by frequency of occurrence of the key sets.\n" "\tThis should decrease the search time dramatically.\n" "-p\tChanges the return value of the generated function ``in_word_set''\n" "\tfrom its default boolean value (i.e., 0 or 1), to type ``pointer\n" "\tto wordlist array'' This is most useful when the -t option, allowing\n" "\tuser-defined structs, is used.\n" "-r\tUtilizes randomness to initialize the associated values table.\n" "-s\tAffects the size of the generated hash table. The numeric argument\n" "\tfor this option indicates ``how many times larger or smaller'' the associated\n" "\tvalue range should be, in relationship to the number of keys, e.g. a value of 3\n" "\tmeans ``allow the maximum associated value to be about 3 times larger than the\n" "\tnumber of input keys.'' Conversely, a value of -3 means ``make the maximum\n" "\tassociated value about 3 times smaller than the number of input keys.\n" "\tA larger table should decrease the time required for an unsuccessful search,\n" "\tat the expense of extra table space. Default value is 1.\n" "-S\tCauses the generated C code to use a switch statement scheme, rather\n" "\tthan an array lookup table. This can lead to a reduction in both\n" "\ttime and space requirements for some keyfiles. The argument to\n" "\tthis option determines how many switch statements are generated.\n" "\tA value of 1 generates 1 switch containing all the elements, a value of 2\n" "\tgenerates 2 tables with 1/2 the elements in each table, etc. This\n" "\tis useful since many C compilers cannot correctly generate code for\n" "\tlarge switch statements.\n" "-t\tAllows the user to include a structured type declaration for \n" "\tgenerated code. Any text before %%%% is consider part of the type\n" "\tdeclaration. Key words and additional fields may follow this, one\n" "\tgroup of fields per line.\n" "-T\tPrevents the transfer of the type declaration to the output file.\n" "\tUse this option if the type is already defined elsewhere.\n" "-v\tPrints out the current version number\n%e%a\n", DEFAULT_JUMP_VALUE, (MAX_KEY_POS - 1), usage); } case 'H': /* Sets the name for the hash function */ { hash_name = getopt.optarg; break; } case 'i': /* Sets the initial value for the associated values array. */ { if ((initial_asso_value = atoi (getopt.optarg)) < 0) report_error ("Initial value %d should be non-zero, ignoring and continuing.\n", initial_asso_value); if (option[RANDOM]) report_error ("warning, -r option superceeds -i, ignoring -i option and continuing\n"); break; } case 'j': /* Sets the jump value, must be odd for later algorithms. */ { if ((jump = atoi (getopt.optarg)) < 0) report_error ("Jump value %d must be a positive number.\n%e%a", jump, usage); else if (jump && even (jump)) report_error ("Jump value %d should be odd, adding 1 and continuing...\n", jump++); break; } case 'k': /* Sets key positions used for hash function. */ { const int BAD_VALUE = -1; int value; Iterator expand (getopt.optarg, 1, MAX_KEY_POS - 1, WORD_END, BAD_VALUE, EOS); if (*getopt.optarg == '*') /* Use all the characters for hashing!!!! */ option_word = (option_word & ~DEFAULTCHARS) | ALLCHARS; else { char *key_pos; for (key_pos = key_positions; (value = expand ()) != EOS; key_pos++) if (value == BAD_VALUE) report_error ("Illegal key value or range, use 1,2,3-%d,'$' or '*'.\n%e%a", MAX_KEY_POS - 1, usage); else *key_pos = value;; *key_pos = EOS; if (! (total_keysig_size = (key_pos - key_positions))) report_error ("No keys selected.\n%e%a", usage); else if (! key_sort (key_positions, total_keysig_size)) report_error ("Duplicate keys selected\n%e%a", usage); if (total_keysig_size != 2 || (key_positions[0] != 1 || key_positions[1] != WORD_END)) option_word &= ~DEFAULTCHARS; } break; } case 'K': /* Make this the keyname for the keyword component field. */ { key_name = getopt.optarg; break; } case 'l': /* Create length table to avoid extra string compares. */ { option_word |= LENTABLE; break; } case 'L': /* Deal with different generated languages. */ { option_word &= ~C; if (!strcmp (getopt.optarg, "C++")) option_word |= (CPLUSPLUS | ANSI); else if (!strcmp (getopt.optarg, "C")) option_word |= C; else { report_error ("unsupported language option %s, defaulting to C\n", getopt.optarg); option_word |= C; } break; } case 'n': /* Don't include the length when computing hash function. */ { option_word |= NOLENGTH; break; } case 'N': /* Make generated lookup function name be optarg */ { class_name = function_name = getopt.optarg; break; } case 'o': /* Order input by frequency of key set occurrence. */ { option_word |= ORDER; break; } case 'p': /* Generated lookup function now a pointer instead of int. */ { option_word |= POINTER; break; } case 'r': /* Utilize randomness to initialize the associated values table. */ { option_word |= RANDOM; if (option.initial_asso_value != 0) report_error ("warning, -r option superceeds -i, disabling -i option and continuing\n"); break; } case 's': /* Range of associated values, determines size of final table. */ { if (abs (size = atoi (getopt.optarg)) > 50) report_error ("%d is excessive, did you really mean this?! (type %n -h for help)\n", size); break; } case 'S': /* Generate switch statement output, rather than lookup table. */ { option_word |= SWITCH; if ((option.total_switches = atoi (getopt.optarg)) <= 0) report_error ("number of switches %s must be a positive number\n%e%a", getopt.optarg, usage); break; } case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */ { option_word |= TYPE; break; } case 'T': /* Don't print structure definition. */ { option_word |= NOTYPE; break; } case 'v': /* Print out the version and quit. */ report_error ("%n: version %s\n%e%a\n", version_string, usage); default: report_error ("%e%a", usage); } } if (argv[getopt.optind] && ! freopen (argv[getopt.optind], "r", stdin)) report_error ("Unable to read key word file %s.\n%e%a", argv[getopt.optind], usage); if (++getopt.optind < argc) report_error ("Extra trailing arguments to %n.\n%e%a", usage); } #ifndef __OPTIMIZE__ /* TRUE if option enable, else FALSE. */ int Options::operator[] (Option_Type option) { return option_word & option; } /* Enables option OPT. */ void Options::operator= (enum Option_Type opt) { option_word |= opt; } /* Disables option OPT. */ void Options::operator!= (enum Option_Type opt) { option_word &= ~opt; } /* Initializes the key Iterator. */ void Options::reset (void) { key_pos = 0; } /* Returns current key_position and advances index. */ int Options::get (void) { return key_positions[key_pos++]; } /* Sets the size of the table size. */ void Options::set_asso_max (int r) { size = r; } /* Returns the size of the table size. */ int Options::get_asso_max (void) { return size; } /* Returns total distinct key positions. */ int Options::get_max_keysig_size (void) { return total_keysig_size; } /* Sets total distinct key positions. */ void Options::set_keysig_size (int size) { total_keysig_size = size; } /* Returns the jump value. */ int Options::get_jump (void) { return jump; } /* Returns the lookup function name. */ const char * Options::get_function_name (void) { return function_name; } /* Returns the keyword key name. */ const char * Options::get_key_name (void) { return key_name; } /* Returns the hash function name. */ const char * Options::get_hash_name (void) { return hash_name; } /* Returns the generated class name. */ const char * Options::get_class_name (void) { return class_name; } /* Returns the initial associated character value. */ int Options::initial_value (void) { return initial_asso_value; } /* Returns the iterations value. */ int Options::get_iterations (void) { return iterations; } /* Returns the string used to delimit keywords from other attributes. */ const char * Options::get_delimiter () { return delimiters; } /* Gets the total number of switch statements to generate. */ int Options::get_total_switches () { return total_switches; } #endif /* not defined __OPTIMIZE__ */ ial associated character value.libg++/gperf/src/key-list.cc 644 473 0 112135 4677677676 11173 /* Routines for building, ordering, and printing the keyword list. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #ifdef sparc #include #endif #include "options.h" #include "read-line.h" #include "hash-table.h" #include "key-list.h" /* Efficiently returns the least power of two greater than or equal to X! */ #define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X))) /* How wide the printed field width must be to contain the maximum hash value. */ static int field_width = 0; /* Destructor dumps diagnostics during debugging. */ Key_List::~Key_List (void) { if (option[DEBUG]) { fprintf (stderr, "\nDumping key list information:\ntotal non-static linked keywords = %d" "\ntotal keywords = %d\ntotal duplicates = %d\nmaximum key length = %d\n", list_len, total_keys, total_duplicates, max_key_len); dump (); report_error ("End dumping list.\n\n"); } } /* Gathers the input stream into a buffer until one of two things occur: 1. We read a '%' followed by a '%' 2. We read a '%' followed by a '}' The first symbolizes the beginning of the keyword list proper, The second symbolizes the end of the C source code to be generated verbatim in the output file. I assume that the keys are separated from the optional preceding struct declaration by a consecutive % followed by either % or } starting in the first column. The code below uses an expandible buffer to scan off and return a pointer to all the code (if any) appearing before the delimiter. */ char * Key_List::get_special_input (char delimiter) { int size = 80; char *buf = new char[size]; int c, i; for (i = 0; (c = getchar ()) != EOF; i++) { if (c == '%') { if ((c = getchar ()) == delimiter) { while ((c = getchar ()) != '\n') ; /* discard newline */ if (i == 0) return ""; else { buf[delimiter == '%' && buf[i - 2] == ';' ? i - 2 : i - 1] = '\0'; return buf; } } else buf[i++] = '%'; } else if (i >= size) /* Yikes, time to grow the buffer! */ { char *temp = new char[size *= 2]; int j; for (j = 0; j < i; j++) temp[j] = buf[j]; buf = temp; } buf[i] = c; } return 0; /* Problem here. */ } /* Stores any C text that must be included verbatim into the generated code output. */ char * Key_List::save_include_src (void) { int c; if ((c = getchar ()) != '%') ungetc (c, stdin); else if ((c = getchar ()) != '{') report_error ("internal error, %c != '{' on line %d in file %s%a", c, __LINE__, __FILE__); else return get_special_input ('}'); return ""; } /* Determines from the input file whether the user wants to build a table from a user-defined struct, or whether the user is content to simply use the default array of keys. */ char * Key_List::get_array_type (void) { return get_special_input ('%'); } /* strcspn - find length of initial segment of S consisting entirely of characters not from REJECT (borrowed from Henry Spencer's ANSI string package, when GNU libc comes out I'll replace this...). */ static inline int Key_List::strcspn (const char *s, const char *reject) { const char *scan; const char *rej_scan; int count = 0; for (scan = s; *scan; scan++) { for (rej_scan = reject; *rej_scan; rej_scan++) if (*scan == *rej_scan) return count; count++; } return count; } /* Sets up the Return_Type, the Struct_Tag type and the Array_Type based upon various user Options. */ void Key_List::set_output_types (void) { if (option[TYPE] && !(array_type = get_array_type ())) return; /* Something's wrong, bug we'll catch it later on.... */ else if (option[TYPE]) /* Yow, we've got a user-defined type... */ { int struct_tag_length = strcspn (array_type, "{\n\0"); if (option[POINTER]) /* And it must return a pointer... */ { return_type = new char[struct_tag_length + 2]; strncpy (return_type, array_type, struct_tag_length); return_type[struct_tag_length] = '*'; return_type[struct_tag_length + 1] = '\0'; } struct_tag = new char[struct_tag_length + 1]; strncpy (struct_tag, array_type, struct_tag_length); struct_tag[struct_tag_length] = '\0'; } else if (option[POINTER]) /* Return a char *. */ return_type = default_array_type; } /* Reads in all keys from standard input and creates a linked list pointed to by Head. This list is then quickly checked for ``links,'' i.e., unhashable elements possessing identical key sets and lengths. */ void Key_List::read_keys (void) { char *ptr; include_src = save_include_src (); set_output_types (); /* Oops, problem with the input file. */ if (! (ptr = Read_Line::get_line ())) report_error ("No words in input file, did you forget to prepend %s" " or use -t accidentally?\n%a", "%%"); /* Read in all the keywords from the input file. */ else { const char *delimiter = option.get_delimiter (); List_Node *temp, *trail = 0; head = new List_Node (ptr, strcspn (ptr, delimiter)); for (temp = head; (ptr = Read_Line::get_line ()) && strcmp (ptr, "%%"); temp = temp->next) { temp->next = new List_Node (ptr, strcspn (ptr, delimiter)); total_keys++; } /* See if any additional C code is included at end of this file. */ if (ptr) additional_code = 1; /* Hash table this number of times larger than keyword number. */ int table_size = (list_len = total_keys) * TABLE_MULTIPLE; /* By allocating the memory here we save on dynamic allocation overhead. Table must be a power of 2 for the hash function scheme to work. */ List_Node *table[POW (table_size)]; /* Make large hash table for efficiency. */ Hash_Table found_link (table, table_size); /* Test whether there are any links and also set the maximum length of an identifier in the keyword list. */ for (temp = head; temp; temp = temp->next) { List_Node *ptr = found_link (temp, option[NOLENGTH]); /* Check for links. We deal with these by building an equivalence class of all duplicate values (i.e., links) so that only 1 keyword is representative of the entire collection. This *greatly* simplifies processing during later stages of the program. */ if (ptr) { total_duplicates++; list_len--; trail->next = temp->next; temp->link = ptr->link; ptr->link = temp; /* Complain if user hasn't enabled the duplicate option. */ if (!option[DUP] || option[DEBUG]) report_error ("Key link: \"%s\" = \"%s\", with key set \"%s\".\n", temp->key, ptr->key, temp->char_set); } else trail = temp; /* Update minimum and maximum keyword length, if needed. */ max_key_len >?= temp->length; min_key_len length; } /* Exit program if links exists and option[DUP] not set, since we can't continue */ if (total_duplicates) report_error (option[DUP] ? "Some input keys have identical hash values, examine output carefully...\n" : "Some input keys have identical hash values,\ntry different key positions or use option -D.\n%a"); if (option[ALLCHARS]) option.set_keysig_size (max_key_len); } } /* Recursively merges two sorted lists together to form one sorted list. The ordering criteria is by frequency of occurrence of elements in the key set or by the hash value. This is a kludge, but permits nice sharing of almost identical code without incurring the overhead of a function call comparison. */ List_Node * Key_List::merge (List_Node *list1, List_Node *list2) { if (!list1) return list2; else if (!list2) return list1; else if (occurrence_sort && list1->occurrence < list2->occurrence || hash_sort && list1->hash_value > list2->hash_value) { list2->next = merge (list2->next, list1); return list2; } else { list1->next = merge (list1->next, list2); return list1; } } /* Applies the merge sort algorithm to recursively sort the key list by frequency of occurrence of elements in the key set. */ List_Node * Key_List::merge_sort (List_Node *head) { if (!head || !head->next) return head; else { List_Node *middle = head; List_Node *temp = head->next->next; while (temp) { temp = temp->next; middle = middle->next; if (temp) temp = temp->next; } temp = middle->next; middle->next = 0; return merge (merge_sort (head), merge_sort (temp)); } } /* Returns the frequency of occurrence of elements in the key set. */ static inline int Key_List::get_occurrence (List_Node *ptr) { int value = 0; char *temp; for (temp = ptr->char_set; *temp; temp++) value += occurrences[*temp]; return value; } /* Enables the index location of all key set elements that are now determined. */ static inline void Key_List::set_determined (List_Node *ptr) { char *temp; for (temp = ptr->char_set; *temp; temp++) determined[*temp] = 1; } /* Returns TRUE if PTR's key set is already completely determined. */ static inline int Key_List::already_determined (List_Node *ptr) { int is_determined = 1; char *temp; for (temp = ptr->char_set; is_determined && *temp; temp++) is_determined = determined[*temp]; return is_determined; } /* Reorders the table by first sorting the list so that frequently occuring keys appear first, and then the list is reorded so that keys whose values are already determined will be placed towards the front of the list. This helps prune the search time by handling inevitable collisions early in the search process. See Cichelli's paper from Jan 1980 JACM for details.... */ void Key_List::reorder (void) { List_Node *ptr; for (ptr = head; ptr; ptr = ptr->next) ptr->occurrence = get_occurrence (ptr); hash_sort = 0; occurrence_sort = 1; for (ptr = head = merge_sort (head); ptr->next; ptr = ptr->next) { set_determined (ptr); if (already_determined (ptr->next)) continue; else { List_Node *trail_ptr = ptr->next; List_Node *run_ptr = trail_ptr->next; for (; run_ptr; run_ptr = trail_ptr->next) { if (already_determined (run_ptr)) { trail_ptr->next = run_ptr->next; run_ptr->next = ptr->next; ptr = ptr->next = run_ptr; } else trail_ptr = run_ptr; } } } } /* Outputs the maximum and minimum hash values. Since the list is already sorted by hash value all we need to do is find the final item! */ void Key_List::output_min_max () { List_Node *temp; for (temp = head; temp->next; temp = temp->next) ; min_hash_value = head->hash_value; max_hash_value = temp->hash_value; if (option[C]) printf ("\n#define TOTAL_KEYWORDS %d\n#define MIN_WORD_LENGTH %d" "\n#define MAX_WORD_LENGTH %d\n#define MIN_HASH_VALUE %d" "\n#define MAX_HASH_VALUE %d\n", total_keys, min_key_len, max_key_len, min_hash_value, max_hash_value); printf ("/* maximum key range = %d, duplicates = %d */\n\n", max_hash_value - min_hash_value + 1, total_duplicates); } /* Generates the output using a C switch. This trades increased search time for decreased table space (potentially *much* less space for sparse tables). It the user has specified their own struct in the keyword file *and* they enable the POINTER option we have extra work to do. The solution here is to maintain a local static array of user defined struct's, as with the Output_Lookup_Function. Then we use for switch statements to perform either a strcmp or strncmp, returning 0 if the str fails to match, and otherwise returning a pointer to appropriate index location in the local static array. */ void Key_List::output_switch (void) { char *comp_buffer; List_Node *curr = head; int pointer_and_type_enabled = option[POINTER] && option[TYPE]; int total_switches = option.get_total_switches (); int switch_size = keyword_list_length () / total_switches; if (pointer_and_type_enabled) { comp_buffer = (char *) alloca (strlen ("*str == *resword->%s && !strncmp (str + 1, resword->%s + 1, len - 1)") + 2 * strlen (option.get_key_name ()) + 1); sprintf (comp_buffer, option[COMP] ? "*str == *resword->%s && !strncmp (str + 1, resword->%s + 1, len - 1)" : "*str == *resword->%s && !strcmp (str + 1, resword->%s + 1)", option.get_key_name (), option.get_key_name ()); } else comp_buffer = option[COMP] ? "*str == *resword && !strncmp (str + 1, resword + 1, len - 1)" : "*str == *resword && !strcmp (str + 1, resword + 1)"; printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n {\n" " register int key = %s (str, len);\n\n" " if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n {\n", option.get_hash_name ()); /* Properly deal with user's who request multiple switch statements. */ while (curr) { List_Node *temp = curr; int lowest_case_value = curr->hash_value; int number_of_cases = 0; /* Figure out a good cut point to end this switch. */ for (; temp && ++number_of_cases < switch_size; temp = temp->next) if (temp->next && temp->hash_value == temp->next->hash_value) while (temp->next && temp->hash_value == temp->next->hash_value) temp = temp->next; if (temp) printf (" if (key <= %d)\n {\n", temp->hash_value); else printf (" {\n"); /* Output each keyword as part of a switch statement indexed by hash value. */ if (option[POINTER] || option[DUP]) { int i = 0; printf (" %s%s *resword; %s\n\n", option[CONST] ? "const " : "", pointer_and_type_enabled ? struct_tag : "char", option[LENTABLE] && !option[DUP] ? "int key_len;" : ""); printf (" switch (key - %d)\n {\n", lowest_case_value); for (temp = curr; temp && ++i <= number_of_cases; temp = temp->next) { printf (" case %*d:", field_width, temp->hash_value - lowest_case_value); if (option[DEBUG]) printf (" /* hash value = %4d, keyword = \"%s\" */", temp->hash_value, temp->key); putchar ('\n'); /* Handle `natural links,' i.e., those that occur statically. */ if (temp->link) { List_Node *links; for (links = temp; links; links = links->link) { if (pointer_and_type_enabled) printf (" resword = &wordlist[%d];\n", links->index); else printf (" resword = \"%s\";\n", links->key); printf (" if (%s) return resword;\n", comp_buffer); } } /* Handle unresolved duplicate hash values. These are guaranteed to be adjacent since we sorted the keyword list by increasing hash values. */ if (temp->next && temp->hash_value == temp->next->hash_value) { for ( ; temp->next && temp->hash_value == temp->next->hash_value; temp = temp->next) { if (pointer_and_type_enabled) printf (" resword = &wordlist[%d];\n", temp->index); else printf (" resword = \"%s\";\n", temp->key); printf (" if (%s) return resword;\n", comp_buffer); } if (pointer_and_type_enabled) printf (" resword = &wordlist[%d];\n", temp->index); else printf (" resword = \"%s\";\n", temp->key); printf (" return %s ? resword : 0;\n", comp_buffer); } else if (temp->link) printf (" return 0;\n"); else { if (pointer_and_type_enabled) printf (" resword = &wordlist[%d];", temp->index); else printf (" resword = \"%s\";", temp->key); if (option[LENTABLE] && !option[DUP]) printf (" key_len = %d;", temp->length); printf (" break;\n"); } } printf (" default: return 0;\n }\n"); printf (option[LENTABLE] && !option[DUP] ? " if (len == key_len && %s)\n return resword;\n" : " if (%s)\n return resword;\n", comp_buffer); printf (" return 0;\n }\n"); curr = temp; } else /* Nothing special required here. */ { int i = 0; printf (" char *s;\n\n switch (key - %d)\n {\n", lowest_case_value); for (temp = curr; temp && ++i <= number_of_cases; temp = temp->next) if (option[LENTABLE]) printf (" case %*d: if (len == %d) s = \"%s\"; else return 0; break;\n", field_width, temp->hash_value - lowest_case_value, temp->length, temp->key); else printf (" case %*d: s = \"%s\"; break;\n", field_width, temp->hash_value - lowest_case_value, temp->key); printf (" default: return 0;\n }\n "); printf ("return *s == *str && !%s;\n }\n", option[COMP] ? "strncmp (s + 1, str + 1, len - 1)" : "strcmp (s + 1, str + 1)"); curr = temp; } } printf (" }\n }\n return 0;\n}\n"); } /* Prints out a table of keyword lengths, for use with the comparison code in generated function ``in_word_set.'' */ void Key_List::output_keylength_table (void) { const int max_column = 15; int index = 0; int column = 0; char *indent = option[GLOBAL] ? "" : " "; List_Node *temp; if (!option[DUP] && !option[SWITCH]) { printf ("\n%sstatic %sunsigned %s lengthtable[] =\n%s%s{\n ", indent, option[CONST] ? "const " : "", max_key_len <= MAX_UNSIGNED_CHAR ? "char" : (max_key_len <= MAX_UNSIGNED_SHORT ? "short" : "long"), indent, indent); for (temp = head; temp; temp = temp->next, index++) { if (index < temp->hash_value) for ( ; index < temp->hash_value; index++) printf ("%3d,%s", 0, ++column % (max_column - 1) ? "" : "\n "); printf ("%3d,%s", temp->length, ++column % (max_column - 1 ) ? "" : "\n "); } printf ("\n%s%s};\n", indent, indent); } } /* Prints out the array containing the key words for the Gen_Perf hash function. */ void Key_List::output_keyword_table (void) { char *l_brace = *head->rest ? "{" : ""; char *r_brace = *head->rest ? "}," : ""; char *indent = option[GLOBAL] ? "" : " "; int index = 0; List_Node *temp; printf ("\n%sstatic %s%swordlist[] =\n%s%s{\n", indent, option[CONST] ? "const " : "", struct_tag, indent, indent); /* Skip over leading blank entries if there are no duplicates. */ if (total_duplicates == 0) while (index < head->hash_value) index++; /* Generate an array of reserved words at appropriate locations. */ for (temp = head ; temp; temp = temp->next, index++) { temp->index = index; if (!option[SWITCH] && (total_duplicates == 0 || !option[DUP]) && index < temp->hash_value) { int column; printf (" "); for (column = 1; index < temp->hash_value; index++, column++) printf ("%s\"\",%s %s", l_brace, r_brace, column % 9 ? "" : "\n "); if (column % 10) printf ("\n"); else { printf ("%s\"%s\", %s%s\n", l_brace, temp->key, temp->rest, r_brace); continue; } } printf (" %s\"%s\", %s%s\n", l_brace, temp->key, temp->rest, r_brace); /* Deal with links specially. */ if (temp->link) for (List_Node *links = temp->link; links; links = links->link) { links->index = ++index; printf (" %s\"%s\", %s%s\n", l_brace, links->key, links->rest, r_brace); } } printf ("%s%s};\n\n", indent, indent); } /* Generates C code for the hash function that returns the proper encoding for each key word. */ void Key_List::output_hash_function (void) { const int max_column = 10; int count = max_hash_value; /* Calculate maximum number of digits required for MAX_HASH_VALUE. */ for (field_width = 2; (count /= 10) > 0; field_width++) ; if (option[GNU]) printf ("#ifdef __GNUC__\ninline\n#endif\n"); if (option[C]) printf ("static "); printf ("unsigned int\n"); if (option[CPLUSPLUS]) printf ("%s::", option.get_class_name ()); printf (option[ANSI] ? "%s (register const char *str, register int len)\n{\n static %sunsigned %s asso_values[] =\n {" : "%s (str, len)\n register char *str;\n register int unsigned len;\n{\n static %sunsigned %s asso_values[] =\n {", option.get_hash_name (), option[CONST] ? "const " : "", max_hash_value <= MAX_UNSIGNED_CHAR ? "char" : (max_hash_value <= MAX_UNSIGNED_SHORT ? "short" : "int")); for (count = 0; count < ALPHA_SIZE; ++count) { if (!(count % max_column)) printf ("\n "); printf ("%*d,", field_width, occurrences[count] ? asso_values[count] : max_hash_value + 1); } /* Optimize special case of ``-k 1,$'' */ if (option[DEFAULTCHARS]) printf ("\n };\n return %sasso_values[str[len - 1]] + asso_values[str[0]];\n}\n\n", option[NOLENGTH] ? "" : "len + "); else { int key_pos; option.reset (); /* Get first (also highest) key position. */ key_pos = option.get (); /* We can perform additional optimizations here. */ if (!option[ALLCHARS] && key_pos <= min_key_len) { printf ("\n };\n return %s", option[NOLENGTH] ? "" : "len + "); for (; key_pos != WORD_END; ) { printf ("asso_values[str[%d]]", key_pos - 1); if ((key_pos = option.get ()) != EOS) printf (" + "); else break; } printf ("%s;\n}\n\n", key_pos == WORD_END ? "asso_values[str[len - 1]]" : ""); } /* We've got to use the correct, but brute force, technique. */ else { printf ("\n };\n register int hval = %s;\n\n switch (%s)\n {\n default:\n", option[NOLENGTH] ? "0" : "len", option[NOLENGTH] ? "len" : "hval"); /* User wants *all* characters considered in hash. */ if (option[ALLCHARS]) { int i; for (i = max_key_len; i > 0; i--) printf (" case %d:\n hval += asso_values[str[%d]];\n", i, i - 1); printf (" }\n return hval;\n}\n\n"); } else /* do the hard part... */ { count = key_pos + 1; do { while (--count > key_pos) printf (" case %d:\n", count); printf (" case %d:\n hval += asso_values[str[%d]];\n", key_pos, key_pos - 1); } while ((key_pos = option.get ()) != EOS && key_pos != WORD_END); printf (" }\n return hval%s;\n}\n\n", key_pos == WORD_END ? " + asso_values[str[len - 1]]" : ""); } } } } /* Generates the large, sparse table that maps hash values into the smaller, contiguous range of the keyword table. */ void Key_List::output_lookup_array (void) { const int DEFAULT_VALUE = -1; struct dup { int hash_value; /* Hash value for this particular duplicate set. */ int index; /* Index into the main keyword storage array. */ int count; /* Number of consecutive duplicates at this index. */ }; dup duplicates[total_duplicates], *dup_ptr = duplicates; int lookup_array[max_hash_value + 1], *lookup_ptr = lookup_array + max_hash_value + 1; List_Node *temp; while (lookup_ptr > lookup_array) *--lookup_ptr = DEFAULT_VALUE; for (temp = head; temp; temp = temp->next) { lookup_array[temp->hash_value] = temp->index; if (option[DEBUG]) fprintf (stderr, "keyword = %s, index = %d\n", temp->key, temp->index); if (temp->link) { List_Node *ptr; lookup_array[temp->hash_value] = MIN_SIGNED_SHORT; *dup_ptr = (struct dup){ temp->hash_value, temp->index, 1 }; for (ptr = temp->link; ptr; ptr = ptr->link) { dup_ptr->count++; if (option[DEBUG]) fprintf (stderr, "keyword = %s, index = %d\n", ptr->key, ptr->index); } } if (temp->next && temp->hash_value == temp->next->hash_value) { if (lookup_array[temp->hash_value] != MIN_SIGNED_SHORT) { lookup_array[temp->hash_value] = MIN_SIGNED_SHORT; *dup_ptr = (struct dup){ temp->hash_value, temp->index, 1 }; } for ( ; temp->next && temp->hash_value == temp->next->hash_value; temp = temp->next) { dup_ptr->count++; if (option[DEBUG]) fprintf (stderr, "keyword = %s, index = %d\n", temp->key, temp->index); } dup_ptr++; } else if (temp->link) dup_ptr++; } while (--dup_ptr >= duplicates) { int i; if (option[DEBUG]) fprintf (stderr, "dup_ptr[%d]: hash_value = %d, index = %d, count = %d\n", dup_ptr - duplicates, dup_ptr->hash_value, dup_ptr->index, dup_ptr->count); /* Start searching for available space towards the right part of the lookup array. */ for (i = dup_ptr->hash_value; i < max_hash_value; i++) if (lookup_array[i] == DEFAULT_VALUE && lookup_array[i + 1] == DEFAULT_VALUE) { lookup_array[i] = -dup_ptr->index; lookup_array[i + 1] = -dup_ptr->count; lookup_array[dup_ptr->hash_value] = total_keys + (i - dup_ptr->hash_value); break; } /* If we didn't find it to the right look to the left instead... */ if (i == max_hash_value) { for (i = dup_ptr->hash_value; i > 0; i--) if (lookup_array[i] == DEFAULT_VALUE && lookup_array[i - 1] == DEFAULT_VALUE) { lookup_array[i - 1] = -dup_ptr->index; lookup_array[i] = -dup_ptr->count; lookup_array[dup_ptr->hash_value] = -(total_keys + (dup_ptr->hash_value - i + 1)); break; } /* We are in big trouble if this happens! */ assert (i != 0); } } int max = NEG_MAX_INT; for (lookup_ptr = lookup_array + max_hash_value + 1; lookup_ptr > lookup_array; max >?= abs (*--lookup_ptr)) ; printf (" static %s%s lookup[] =\n {\n ", option[CONST] ? "const " : "", max <= MAX_UNSIGNED_CHAR ? "char" : (max <= MAX_UNSIGNED_SHORT ? "short" : "int")); int count = max; /* Calculate maximum number of digits required for MAX_HASH_VALUE. */ for (field_width = 2; (count /= 10) > 0; field_width++) ; /* Skip over the leading default entries. */ for (lookup_ptr = lookup_array; lookup_ptr < lookup_array + min_hash_value; lookup_ptr++) assert (*lookup_ptr == DEFAULT_VALUE); assert (*lookup_ptr != DEFAULT_VALUE); const int max_column = 15; int column = 0; for ( ; lookup_ptr < lookup_array + max_hash_value + 1; lookup_ptr++) printf ("%*d,%s", field_width, *lookup_ptr, ++column % (max_column - 1) ? "" : "\n "); printf ("\n };\n\n"); } /* Generates C code to perform the keyword lookup. */ void Key_List::output_lookup_function (void) { printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n {\n" " register int key = %s (str, len) - MIN_HASH_VALUE;\n\n" " if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0)\n {\n", option.get_hash_name ()); if (option[DUP]) { printf (" register int index = lookup[key];\n\n" " if (index >= 0 && index < TOTAL_KEYWORDS)\n" " {\n" " register %schar *s = wordlist[index]", option[CONST] ? "const " : ""); if (array_type != default_array_type) printf (".%s", option.get_key_name ()); printf (";\n\n if (%s*s == *str && !%s)\n return %s;\n }\n", option[LENTABLE] ? "len == lengthtable[key]\n && " : "", option[COMP] ? "strncmp (str + 1, s + 1, len - 1)" : "strcmp (str + 1, s + 1)", option[TYPE] && option[POINTER] ? "&wordlist[key]" : "s"); printf (" else if (index < 0 && index >= -TOTAL_KEYWORDS)\n" " return 0;\n else\n {\n" " register int offset = key + index + (index > 0 ? -TOTAL_KEYWORDS : TOTAL_KEYWORDS);\n" " register %s%s*base = &wordlist[-lookup[offset]];\n" " register %s%s*ptr = base + -lookup[offset + 1];\n\n" " while (--ptr >= base)\n ", option[CONST] ? "const " : "", struct_tag, option[CONST] ? "const " : "", struct_tag); if (array_type != default_array_type) printf ("if (*str == *ptr->%s && !strcmp (str + 1, ptr->%s + 1", option.get_key_name (), option.get_key_name ()); else printf ("if (*str == **ptr && !strcmp (str + 1, *ptr + 1"); printf ("))\n return %sptr;" "\n }\n }\n }\n return 0;\n}\n", array_type == default_array_type ? "*" : ""); } else { printf (" register %schar *s = wordlist[key]", option[CONST] ? "const " : ""); if (array_type != default_array_type) printf (".%s", option.get_key_name ()); printf (";\n\n if (%s*s == *str && !%s)\n return %s", option[LENTABLE] ? "len == lengthtable[key]\n && " : "", option[COMP] ? "strncmp (str + 1, s + 1, len - 1)" : "strcmp (str + 1, s + 1)", option[TYPE] && option[POINTER] ? "&wordlist[key]" : "s"); printf (";\n }\n }\n return 0;\n}\n"); } } /* Generates the hash function and the key word recognizer function based upon the user's Options. */ void Key_List::output (void) { int global_table = option[GLOBAL]; printf ("%s\n", include_src); if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */ printf ("%s;\n", array_type); output_min_max (); if (option[CPLUSPLUS]) printf ("class %s\n{\nprivate:\n const int MIN_WORD_LENGTH, MAX_WORD_LENGTH, MIN_HASH_VALUE, MAX_HASH_VALUE;\n" " unsigned int hash (const char *str, int len);\npublic:\n %s (void):\n" " MIN_WORD_LENGTH (%d), MAX_WORD_LENGTH (%d), MIN_HASH_VALUE (%d), MAX_HASH_VALUE (%d) {}\n" " %soperator () (const char *str, int len);\n};\n\n", option.get_class_name (), option.get_class_name (), min_key_len, max_key_len, min_hash_value, max_hash_value, return_type); output_hash_function (); if (global_table) if (option[SWITCH]) { if (option[LENTABLE] && option[DUP]) output_keylength_table (); if (option[POINTER] && option[TYPE]) output_keyword_table (); } else { if (option[LENTABLE]) output_keylength_table (); output_keyword_table (); } if (option[GNU]) /* Use the inline keyword to remove function overhead. */ printf ("#ifdef __GNUC__\ninline\n#endif\n"); printf ("%s%s\n", option[CONST] ? "const " : "", return_type); if (option[CPLUSPLUS]) printf ("%s::", option.get_class_name ()); printf (option[ANSI] ? "%s (register const char *str, register int len)\n{\n" : "%s (str, len)\n register char *str;\n register unsigned int len;\n{\n", option[CPLUSPLUS] ? "operator ()" : option.get_function_name ()); /* Use the switch in place of lookup table. */ if (option[SWITCH]) { if (!global_table) { if (option[LENTABLE] && option[DUP]) output_keylength_table (); if (option[POINTER] && option[TYPE]) output_keyword_table (); } output_switch (); } /* Use the lookup table, in place of switch. */ else { if (!global_table) { if (option[LENTABLE]) output_keylength_table (); output_keyword_table (); } if (total_duplicates) output_lookup_array (); output_lookup_function (); } if (additional_code) for (int c; (c = getchar ()) != EOF; putchar (c)) ; fflush (stdout); } /* Sorts the keys by hash value. */ void Key_List::sort (void) { hash_sort = 1; occurrence_sort = 0; head = merge_sort (head); } /* Dumps the key list to stderr stream. */ void Key_List::dump () { int field_width = option.get_max_keysig_size (); fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n", field_width, "char_set"); for (List_Node *ptr = head; ptr; ptr = ptr->next) fprintf (stderr, "%11d,%11d,%6d, %*s, %s\n", ptr->hash_value, ptr->length, ptr->index, field_width, ptr->char_set, ptr->key); } /* Simple-minded constructor action here... */ Key_List::Key_List (void) { total_keys = 1; max_key_len = NEG_MAX_INT; min_key_len = MAX_INT; return_type = default_return_type; array_type = struct_tag = default_array_type; head = 0; total_duplicates = 0; additional_code = 0; } /* Returns the length of entire key list. */ int Key_List::keyword_list_length (void) { return list_len; } /* Returns length of longest key read. */ int Key_List::max_key_length (void) { return max_key_len; } _List::Key_List (void) { total_keys = 1; max_key_len = NEG_MAX_INT; min_key_len = MAX_INT; return_type = default_return_type; array_type = struct_tag = default_array_type; head = 0; total_duplicates = 0; additional_code = 0; } /* Returns the length of entire key list. */ int Key_List::keyword_list_length (void) { return list_len; } /* Returns lengtlibg++/gperf/src/list-node.h 644 473 0 3502 4677677676 11127 /* This may look like C code, but it is really -*- C++ -*- */ /* Data and function members for defining values and operations of a list node. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once #include "std-err.h" #include "vectors.h" struct List_Node : private Std_Err, private Vectors { List_Node *link; /* TRUE if key has an identical KEY_SET as another key. */ List_Node *next; /* Points to next element on the list. */ char *key; /* Each keyword string stored here. */ char *rest; /* Additional information for building hash function. */ char *char_set; /* Set of characters to hash, specified by user. */ int length; /* Length of the key. */ int hash_value; /* Hash value for the key. */ int occurrence; /* A metric for frequency of key set occurrences. */ int index; /* Position of this node relative to other nodes. */ List_Node (char *key, int len); static void set_sort (char *base, int len); }; mation for building hash function. */ char *char_set; /* Set of characters to hash, specified by user. */ int length; /* Length of the key. */ int libg++/gperf/src/std-err.cc 644 473 0 5320 4677677676 10747 /* Provides a useful variable-length argument error handling abstraction. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "std-err.h" /* Sets name of program. */ void Std_Err::set_program_name (char *prog_name) { program_name = prog_name; } /* Valid Options (prefixed by '%', as in printf format strings) include: 'a': exit the program at this point 'c': print a character 'd': print a decimal number 'e': call the function pointed to by the corresponding argument 'f','g': print a double 'n': print the name of the program (NULL if not set in constructor or elsewhere) 'p': print out the appropriate errno value from sys_errlist 's': print out a character string '%': print out a single percent sign, '%' */ void Std_Err::report_error (char *format, ...) { extern int errno, sys_nerr; extern char *sys_errlist[]; typedef void (*PTF)(); va_list argp; int abort = 0; for (va_start (argp,format); *format; format++) { if (*format != '%') putc (*format, stderr); else { switch (*++format) { case '%' : putc ('%', stderr); break; case 'a' : abort = 1; break; case 'c' : putc (va_arg (argp,int), stderr); break; case 'd' : fprintf (stderr, "%d", va_arg (argp,int)); break; case 'e' : (*va_arg (argp, PTF))(); break; case 'f' : fprintf (stderr, "%g", va_arg (argp,double)); break; case 'n' : fputs (program_name ? program_name : "error", stderr); break; case 'p' : if (errno < sys_nerr) fprintf (stderr, "%s: %s", va_arg (argp,char *), sys_errlist[errno]); else fprintf (stderr, " %d", errno); break; case 's' : fputs (va_arg (argp,char *), stderr); break; } } if (abort) exit (1); } va_end (argp); } (argp,double)); break; case 'n' : fputs (program_name ? program_name : "error", stderr); break; case 'p' : if (errno < sys_nerr) fprintf (stderr, "%s: %s", va_arg (argp,char *), sys_errlist[errno]); else fprintf (stdelibg++/gperf/src/iterator.h 644 473 0 4133 4677677676 11063 /* This may look like C code, but it is really -*- C++ -*- */ /* Provides an Iterator for keyword characters. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Provides an Iterator that expands and decodes a control string containing digits and ranges, returning an integer every time the generator function is called. This is used to decode the user's key position requests. For example: "-k 1,2,5-10,$" will return 1, 2, 5, 6, 7, 8, 9, 10, and 0 ( representing the abstract ``last character of the key'' on successive calls to the member function operator (). No errors are handled in these routines, they are passed back to the calling routines via a user-supplied Error_Value */ #pragma once class Iterator { private: char *str; /* A pointer to the string provided by the user. */ int end; /* Value returned after last key is processed. */ int end_word; /* A value marking the abstract ``end of word'' ( usually '$'). */ int error_value; /* Error value returned when input is syntactically erroneous. */ int hi_bound; /* Greatest possible value, inclusive. */ int lo_bound; /* Smallest possible value, inclusive. */ public: Iterator (char *s, int lo, int hi, int word_end, int bad_val, int key_end); int operator () (void); }; returned after last key is processed. */ int end_word; /* A value marking the abstract ``end of word'' ( usually '$'). */ int error_value; /* Error value returned when input is syntactically erroneous. */ int hi_bound; /* Greatest possible value, inclusive. */ int lo_bound; /* Smallest possible value, inclusive. */ public: Iterator (char *slibg++/gperf/src/list-node.cc 644 473 0 7322 4677677677 11272 /* Creates and initializes a new list node. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "options.h" #include "list-node.h" /* Sorts the key set alphabetically to speed up subsequent operations. Uses insertion sort since the set is probably quite small. */ static inline void List_Node::set_sort (char *base, int len) { int i, j; for (i = 0, j = len - 1; i < j; i++) { char curr, tmp; for (curr = i + 1, tmp = base[curr]; curr > 0 && tmp < base[curr-1]; curr--) base[curr] = base[curr - 1]; base[curr] = tmp; } } /* Initializes a List_Node. This requires obtaining memory for the CHAR_SET initializing them using the information stored in the KEY_POSITIONS array in Options, and checking for simple errors. It's important to note that KEY and REST are both pointers to the different offsets into the same block of dynamic memory pointed to by parameter K. The data member REST is used to store any additional fields of the input file (it is set to the "" string if Option[TYPE] is not enabled). This is useful if the user wishes to incorporate a lookup structure, rather than just an array of keys. Finally, KEY_NUMBER contains a count of the total number of keys seen so far. This is used to initialize the INDEX field to some useful value. */ List_Node::List_Node (char *k, int len): key (k), next (0), index (0), length (len), link (0), rest (option[TYPE] ? k + len + 1 : "") { char *ptr = new char[(option[ALLCHARS] ? len : option.get_max_keysig_size ()) + 1]; char_set = ptr; k[len] = '\0'; /* Null terminate KEY to separate it from REST. */ if (option[ALLCHARS]) /* Use all the character position in the KEY. */ for (; *k; k++, ptr++) ++occurrences[*ptr = *k]; else /* Only use those character positions specified by the user. */ { int i; /* Iterate thru the list of key_positions, initializing occurrences table and char_set (via char * pointer ptr). */ for(option.reset (); (i = option.get ()) != EOS; ) { if (i == WORD_END) /* Special notation for last KEY position, i.e. '$'. */ *ptr = key[len - 1]; else if (i <= len) /* Within range of KEY length, so we'll keep it. */ *ptr = key[i - 1]; else /* Out of range of KEY length, so we'll just skip it. */ continue; ++occurrences[*ptr++]; } /* Didn't get any hits and user doesn't want to consider the keylength, so there are essentially no usable hash positions! */ if (ptr == char_set && option[NOLENGTH]) report_error ("Can't hash keyword %s with chosen key positions.\n%a", key); } *ptr = '\0'; /* Terminate this bastard.... */ /* Sort the KEY_SET items alphabetically. */ set_sort (char_set, ptr - char_set); } ip it. */ continue; ++occurrences[*ptr++]; } /* Didn't get any hits and user doesn't want to consider the keylength, so there are essentially no usable hash positions! */ if (ptr == char_set && option[NOLENGTH]) report_error ("Can't hashlibg++/gperf/src/gen-perf.cc 644 473 0 24112 4677677677 11113 /* Provides high-level routines to manipulate the keywork list structures the code generation output. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "options.h" #include "gen-perf.h" /* Current release version. */ extern char *version_string; /* Efficiently returns the least power of two greater than or equal to X! */ #define POW(X) ((!X)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X))) /* Reads input keys, possibly applies the reordering heuristic, sets the maximum associated value size (rounded up to the nearest power of 2), may initialize the associated values array, and determines the maximum hash table size. Note: using the random numbers is often helpful, though not as deterministic, of course! */ Gen_Perf::Gen_Perf (void) { int asso_value_max; int non_linked_length; Key_List::read_keys (); if (option[ORDER]) reorder (); asso_value_max = option.get_asso_max (); non_linked_length = Key_List::keyword_list_length (); num_done = 1; fewest_collisions = 0; if (asso_value_max == 0) asso_value_max = non_linked_length; else if (asso_value_max > 0) asso_value_max *= non_linked_length; else /* if (asso_value_max < 0) */ asso_value_max = non_linked_length / -asso_value_max; option.set_asso_max (POW (asso_value_max)); if (option[RANDOM]) { srandom (time (0)); for (int i = 0; i < ALPHA_SIZE; i++) asso_values[i] = (random () & asso_value_max - 1); } else { int asso_value = option.initial_value (); if (asso_value) /* Initialize array if user requests non-zero default. */ for (int i = ALPHA_SIZE - 1; i >= 0; i--) asso_values[i] = asso_value & option.get_asso_max () - 1; } max_hash_value = Key_List::max_key_length () + option.get_asso_max () * option.get_max_keysig_size (); printf ("/* "); if (option[C]) printf ("C"); else if (option[CPLUSPLUS]) printf ("C++"); printf (" code produced by gperf version %s */\n", version_string); Options::print_options (); if (option[DEBUG]) fprintf (stderr, "total non-linked keys = %d\nmaximum associated value is %d" "\nmaximum size of generated hash table is %d\n", non_linked_length, asso_value_max, max_hash_value); } /* Merge two disjoint hash key multisets to form the ordered disjoint union of the sets. (In a multiset, an element can occur multiple times). Precondition: both set_1 and set_2 must be ordered. Returns the length of the combined set. */ static inline int Gen_Perf::compute_disjoint_union (char *set_1, char *set_2, char *set_3) { char *base = set_3; while (*set_1 && *set_2) if (*set_1 == *set_2) set_1++, set_2++; else { *set_3 = *set_1 < *set_2 ? *set_1++ : *set_2++; if (set_3 == base || *set_3 != *(set_3-1)) set_3++; } while (*set_1) { *set_3 = *set_1++; if (set_3 == base || *set_3 != *(set_3-1)) set_3++; } while (*set_2) { *set_3 = *set_2++; if (set_3 == base || *set_3 != *(set_3-1)) set_3++; } *set_3 = '\0'; return set_3 - base; } /* Sort the UNION_SET in increasing frequency of occurrence. This speeds up later processing since we may assume the resulting set (Set_3, in this case), is ordered. Uses insertion sort, since the UNION_SET is typically short. */ static inline void Gen_Perf::sort_set (char *union_set, int len) { int i, j; for (i = 0, j = len - 1; i < j; i++) { char curr, tmp; for (curr = i + 1, tmp = union_set[curr]; curr > 0 && occurrences[tmp] < occurrences[union_set[curr-1]]; curr--) union_set[curr] = union_set[curr - 1]; union_set[curr] = tmp; } } /* Generate a key set's hash value. */ static inline int Gen_Perf::hash (List_Node *key_node) { int sum = option[NOLENGTH] ? 0 : key_node->length; for (char *ptr = key_node->char_set; *ptr; ptr++) sum += asso_values[*ptr]; return key_node->hash_value = sum; } /* Find out how character value change affects successfully hashed items. Returns FALSE if no other hash values are affected, else returns TRUE. Note that because Option.Get_Asso_Max is a power of two we can guarantee that all legal Asso_Values are visited without repetition since Option.Get_Jump was forced to be an odd value! */ static inline int Gen_Perf::affects_prev (char c, List_Node *curr) { int original_char = asso_values[c]; int total_iterations = !option[FAST] ? option.get_asso_max () : option.get_iterations () ? /* Elided! */ : keyword_list_length (); int i = total_iterations; /* Try all legal associated values. */ while (--i >= 0) { int collisions = 0; asso_values[c] = asso_values[c] + (option.get_jump () ? /* Elided! */ : random ()) & option.get_asso_max () - 1; /* Iteration Number array is a win, O(1) intialization time! */ reset (); /* See how this asso_value change affects previous keywords. If it does better than before we'll take it! */ for (List_Node *ptr = head; !Bool_Array::find (hash (ptr)) || ++collisions < fewest_collisions; ptr = ptr->next) if (ptr == curr) { fewest_collisions = collisions; if (option[DEBUG]) fprintf (stderr, "- resolved after %d iterations", total_iterations - i); return 0; } } /* Restore original values, no more tries. */ asso_values[c] = original_char; /* If we're this far it's time to try the next character.... */ return 1; } /* Change a character value, try least-used characters first. */ static void Gen_Perf::change (List_Node *prior, List_Node *curr) { static char *union_set; if (!union_set) union_set = new char [2 * option.get_max_keysig_size () + 1]; if (option[DEBUG]) { fprintf (stderr, "collision on keyword #%d, prior = \"%s\", curr = \"%s\" hash = %d\n", num_done, prior->key, curr->key, curr->hash_value); fflush (stderr); } sort_set (union_set, compute_disjoint_union (prior->char_set, curr->char_set, union_set)); /* Try changing some values, if change doesn't alter other values continue normal action. */ fewest_collisions++; for (char *temp = union_set; *temp; temp++) if (!affects_prev (*temp, curr)) { if (option[DEBUG]) { fprintf (stderr, " by changing asso_value['%c'] (char #%d) to %d\n", *temp, temp - union_set + 1, asso_values[*temp]); fflush (stderr); } return; /* Good, doesn't affect previous hash values, we'll take it. */ } for (List_Node *ptr = head; ptr != curr; ptr = ptr->next) hash (ptr); hash (curr); if (option[DEBUG]) { fprintf (stderr, "** collision not resolved, %d duplicates remain, continuing...\n", fewest_collisions); fflush (stderr); } } /* Does the hard stuff.... Initializes the Iteration Number array, and attempts to find a perfect function that will hash all the key words without getting any duplications. This is made much easier since we aren't attempting to generate *minimum* functions, only perfect ones. If we can't generate a perfect function in one pass *and* the user hasn't enabled the DUP option, we'll inform the user to try the randomization option, use -D, or choose alternative key positions. The alternatives (e.g., back-tracking) are too time-consuming, i.e, exponential in the number of keys. */ int Gen_Perf::operator () (void) { STORAGE_TYPE buffer[max_hash_value + 1]; Bool_Array::init (buffer, max_hash_value + 1); for (List_Node *curr = head; curr; curr = curr->next) { hash (curr); for (List_Node *ptr = head; ptr != curr; ptr = ptr->next) if (ptr->hash_value == curr->hash_value) { change (ptr, curr); break; } num_done++; } /* Make one final check, just to make sure nothing weird happened.... */ Bool_Array::reset (); for (curr = head; curr; curr = curr->next) if (Bool_Array::find (hash (curr))) if (option[DUP]) /* Keep track of this number... */ total_duplicates++; else /* Yow, big problems. we're outta here! */ { report_error ("\nInternal error, duplicate value %d:\n" "try options -D or -r, or use new key positions.\n\n", hash (curr)); return 1; } /* Sorts the key word list by hash value, and then outputs the list. The generated hash table code is only output if the early stage of processing turned out O.K. */ sort (); output (); return 0; } /* Prints out some diagnostics upon completion. */ Gen_Perf::~Gen_Perf (void) { if (option[DEBUG]) { fprintf (stderr, "\ndumping occurrence and associated values tables\n"); for (int i = 0; i < ALPHA_SIZE; i++) if (occurrences[i]) fprintf (stderr, "asso_values[%c] = %6d, occurrences[%c] = %6d\n", i, asso_values[i], i, occurrences[i]); fprintf (stderr, "end table dumping\n"); } } return 0; } /* Prints out some diagnostics upon completion. */ Gen_Perf::~Gen_Perf (void) { if (option[DEBUG]) { fprintf (stderr, "\ndumping occurrence and associated values tables\n"); for (int i = 0; i < ALPHA_SIZE; i++) if (occurrences[i]) fprintf (stderr, "asso_values[%c] = %6d, occurrences[%c] = %6d\n", i, asso_values[i], i, occurrences[ilibg++/gperf/src/read-line.h 644 473 0 3316 4677677677 11075 /* This may look like C code, but it is really -*- C++ -*- */ /* Reads arbitrarily long string from input file, returning it as a dynamic buffer. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Returns a pointer to an arbitrary length string. Returns NULL on error or EOF The storage for the string is dynamically allocated by new. */ #pragma once #include class Read_Line { private: char *readln_aux (int chunks); FILE *fp; /* FILE pointer to the input stream. */ const int CHUNK_SIZE; /* Size of each chunk. */ public: Read_Line (FILE *stream = stdin, int size = BUFSIZ): fp (stream), CHUNK_SIZE (size) {;} char *get_line (void); }; #ifdef __OPTIMIZE__ inline char *Read_Line::get_line (void) { int c; if ((c = getc (fp)) == '#') { while (getc (fp) != '\n') ; return get_line (); } else { ungetc (c, stdin); return readln_aux (0); } } #endif LE pointer to the input stream. */ const int CHUNK_SIZE; /* Size of each chunk. */ public: Read_Line (FILE *stream = stdin, int size = BUFSIZ): fp (stream), CHUNK_SIZE (size) {;} char *get_line (void); }; #ifdef __OPTIMIZE__ inline char *Read_Line::get_line (void) libg++/gperf/src/hash-table.h 644 473 0 2414 4677677677 11243 /* This may look like C code, but it is really -*- C++ -*- */ /* Hash table used to check for duplicate keyword entries. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once #include "list-node.h" class Hash_Table { private: List_Node **table; /* Vector of pointers to linked lists of List_Node's. */ int size; /* Size of the vector. */ public: Hash_Table (List_Node **t, int s); ~Hash_Table (void); List_Node *operator () (List_Node *item, int ignore_length); }; cense along with GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once #include "list-node.h" class Hash_Table { private: List_Node **table; /* Vector libg++/gperf/src/std-err.h 644 473 0 2200 4677677677 10604 /* This may look like C code, but it is really -*- C++ -*- */ /* Provides a useful variable-length argument error handling abstraction. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once class Std_Err { private: static char *program_name; /* Records the program name. */ public: static void set_program_name (char *prog_name); static void report_error (char *format, ...); }; TY 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma once class Std_Err { private: static char *program_name; /* Records the prlibg++/gperf/src/new.cc 600 473 0 4760 4677677700 10143 /* Defines a buffered memory allocation abstraction that reduces calls to malloc. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "std-err.h" /* Determine default alignment. If your C compiler does not like this then try something like #define DEFAULT_ALIGNMENT 8. */ struct fooalign {char x; double d;}; #define ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0) /* Provide an abstraction that cuts down on the number of calls to NEW by buffering the memory pool from which strings are allocated. */ void * operator new (long size) { static char *buf_start = 0; /* Large array used to reduce calls to NEW. */ static char *buf_end = 0; /* Indicates end of BUF_START. */ static int buf_size = 4 * BUFSIZ; /* Size of buffer pointed to by BUF_START. */ char *temp; /* Align this on correct boundaries, just to be safe... */ size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; /* If we are about to overflow our buffer we'll just grab another chunk of memory. Since we never free the original memory it doesn't matter that no one points to the beginning of that chunk. Note we use a heuristic that grows the buffer either by size of the request or by twice the previous size, whichever is larger. */ if (buf_start + size >= buf_end) { buf_size *= 2; if (buf_start = malloc (buf_size >?= size)) buf_end = buf_start + buf_size; else Std_Err::report_error ("virtual memory failed at %s, %s%a\n", __FILE__, __LINE__); } temp = buf_start; buf_start += size; return temp; } /* We need this destructor in order to make the linker happy. */ void operator delete (void *ptr) { free ((char *) ptr); } t or by twice thlibg++/gperf/src/main.cc 644 473 0 4165 4677677700 10305 /* Driver program for the Gen_Perf hash function generator Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU GPERF. GNU GPERF 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 1, or (at your option) any later version. GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Simple driver program for the Gen_Perf.hash function generator. Most of the hard work is done in class Gen_Perf and its class methods. */ #include #include #include #include #include "std-err.h" #include "options.h" #include "gen-perf.h" int main (int argc, char *argv[]) { struct tm *tm; time_t clock; int status; time (&clock); tm = localtime (&clock); fprintf (stderr, "/* starting time is %d:%02d:%02d */\n", tm->tm_hour, tm->tm_min, tm->tm_sec); #ifdef UNLIMIT_STACK /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } #endif /* UNLIMIT_STACK */ /* Sets the Options. */ option (argc, argv); /* Initializes the key word list. */ Gen_Perf generate_table; /* Generates and prints the Gen_Perf hash table. Don't use exit here, it skips the destructors. */ status = generate_table (); time (&clock); tm = localtime (&clock); fprintf (stderr, "/* ending time is %d:%02d:%02d */\n", tm->tm_hour, tm->tm_min, tm->tm_sec); return status; } setrlimit (RLIMIT_STACK, &rlim); } #endif /* UNLIMIT_STACK */ /* Sets the Options. */ option (argc, argv); /* Initializes the key word list. */ Gen_Perf generate_table; /* Generates and prints the Gen_Perf hash table. Don't use exit here, it skips the destructors. */ status = generate_table (); time (&clock); tm = localtime (&clock); fprintflibg++/gperf/src/Makefile 644 473 0 4371 4677677700 10511 # Copyright (C) 1989 Free Software Foundation, Inc. # written by Douglas C. Schmidt (schmidt@ics.uci.edu) # # This file is part of GNU GPERF. # # GNU GPERF 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 1, or (at your option) # any later version. # # GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. GXX = g++ DFLAGS= -Wall -DLO_CAL -DUNLIMIT_STACK OFLAGS= -O -fdelayed-branch -fsave-memoized \ -finline-functions -fstrength-reduce -felide-constructors GXXFLAGS= $(DFLAGS) $(OFLAGS) OBJS = new.o options.o iterator.o main.o gen-perf.o key-list.o list-node.o \ hash-table.o bool-array.o read-line.o std-err.o version.o LIBS = -lg++ .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< all: gperf gperf: $(OBJS) $(GXX) $(GXXFLAGS) -o gperf $(OBJS) $(LIBS) clean: -rm -f gperf *.o core *~ #*# mon.out # dependencies # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. bool-array.o : bool-array.cc options.h std-err.h bool-array.h gen-perf.o : gen-perf.cc options.h std-err.h gen-perf.h key-list.h \ list-node.h vectors.h read-line.h bool-array.h hash-table.o : hash-table.cc hash-table.h list-node.h std-err.h vectors.h \ options.h iterator.o : iterator.cc iterator.h key-list.o : key-list.cc options.h std-err.h read-line.h hash-table.h \ list-node.h vectors.h key-list.h list-node.o : list-node.cc options.h std-err.h list-node.h vectors.h main.o : main.cc std-err.h options.h gen-perf.h key-list.h list-node.h \ vectors.h read-line.h bool-array.h new.o : new.cc std-err.h options.o : options.cc options.h std-err.h iterator.h read-line.o : read-line.cc std-err.h read-line.h std-err.o : std-err.cc std-err.h version.o : version.cc # IF YOU PUT ANYTHING HERE IT WILL GO AWAY : key-list.cc options.h std-err.h read-line.h hash-table.h \ list-node.h vectors.h key-list.h list-node.o : list-node.cc options.h std-err.h list-node.h vectors.h main.o : main.cc std-err.h options.h gen-perf.h key-list.h list-node.h \ vectors.h read-line.libg++/gperf/ChangeLog 644 473 0 126202 4677677701 10073 Fri Feb 23 14:21:28 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Renamed all instances of member function get_keysig_size to get_max_keysig_size, since this is more precise... * Changed all occurrences of charset to keysig (stands for ``key signature'') to reflect the new naming convention used in the USENIX paper. Thu Feb 22 11:28:36 1990 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Changed the name of the generated associated values table from asso_value to asso_values to reflect conventions in the USENIX C++ paper. Thu Feb 15 23:29:03 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Updated the gperf.texinfo file to fix some formatting problems that had crept in since last time. Wed Feb 14 23:27:24 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed stupid bug in key-list.cc (get_special_input), wher gperf replaced each '%' with the succeeding character. * Added support for multiple target language generation. Currently handled languages are C and C++, with C as the default. Updated documentation and option handler to reflect the changes. * Added a global destructor to new.cc and removed the #ifdef, since the bloody thing now works with libg++. Mon Feb 14 13:00:00 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Found out that my gperf paper was accepted at the upcoming USENIX C++ Conference in San Francisco. Yow! Tue Jan 30 09:00:29 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * #ifdef'd out the new.cc memory allocator, since there are problems with this and the libg++ stuff. * Changed key-list.h so that class Vectors is a public (rather than private) base class for class Key_List. The previous form was illegal C++, but wasn't being caught by the old g++ compiler. Should work now... ;-) Sun Dec 10 14:08:23 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added several changes from rfg@ics.uci.edu. These changes help to automate the build process. Wed Nov 15 15:49:33 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Removed conditional compilation for GATHER_STATISTICS. There's really no good reason to avoid collecting this info at run-time, since that section of code is *hardly* the bottleneck... ;-) * Simplified the C output routines in Key_List::set_output_types and Key_List::output_keyword_table a bit in order to speed-up and clean up the code generation. * Modified function Key_List::get_special_input so that it does not try to `delete' a buffer that turned out to be too short. This is important since the new memory management scheme does not handle deletions. However, adding a small amount of garbage won't hurt anything, since we generally don't do this operation more than a couple times *at most*! * Created a new file (new.cc) which includes my own overloaded operator new. This function should dramatically reduce the number of calls to malloc since it grabs large chunks and doles them out in small pieces. As a result of this change the class-specific `operator new' was removed from class List_Node. Tue Nov 14 21:45:30 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Continued to refine the great hack. The latest trick is to try and replace most uses of dynamic memory (i.e., calls to new) with uses of gcc dynamic arrays (i.e., an alloca solution). This makes life much easier for the overall process-size, since it reduces the amount of overhead for memory management. As a side-effect from this change there is no reason to have the Bool_Array::dispose member function, so it's outta here! * Fixed a stupid bug that was an disaster waiting to happen... Instead of making the boolean array large enough to index max_hash_value it was only large enough to index max_hash_value - 1. Once again, an off-by-one mistake in C/C++!!!! Mon Nov 13 19:38:27 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added the final great hack! This allows us to generate hash tables for near-perfect hash functions that contain duplicates, *without* having to use switch statements! Since many compilers die on large switch statements this feature is essential. Furthermore, it appears that the generated code is often *smaller* than that put out by compilers, even though a large, sparse array must be created. Here's the general idea: a. Generate the wordlist as a contiguous block of keywords, just as before when using a switch statement. This wordlist *must* be sorted by hash value. b. Generate the lookup array, which is an array of signed {chars,shorts,ints}, (which ever allows full coverage of the wordlist dimensions). If the value v, where v = lookup[hash(str,len)], is >= 0 and < TOTAL_KEYWORDS, then we simply use this result as a direct access into the wordlist array to snag the keyword for comparison. c. Otherwise, if v is < -TOTAL_KEYWORDS or > TOTAL_KEYWORDS this is an indication that we'll need to search through some number of duplicates hash values. Using a hash linking scheme we'd then index into a different part of the hash table that provides the starting index and total length of the duplicate entries to find via linear search! Sun Nov 12 13:48:10 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Simplified Key_List::output_min_max considerably by recognizing that since the keyword list was already sorted by hash value finding the min and max values is trivial! * Improved the debugging diagnostics considerably in classes Key_List, Hash_Table, and Gen_Perf. * Modified the `-s' option so that a negative argument is now interpreted to mean `allow the maximum associated value to be about x times *smaller* than the number of input keys.' This should help prevent massive explosion of generated hash table size for large keysets. Sat Nov 11 11:31:13 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added a field in class Key_List that counts the total number of duplicate keywords, both static and dynamic. * Added a new member function Bool_Array that deletes the dynamic memory allocated to Bool_Array::storage_array. This space may be needed for subsequent options, so it made sense to free it as soon as possible... * Renamed file/class Alpha_Vectors to Vectors, to avoid problems with 14 character length filenames on SYSV. Also changed file adapredefined.gperf to adadefs.gperf in the ./tests directory. * Modified class Options by changing the member function Options::total_positions to Options::get_charset_size and Options::set_charset_size. These two routines now either return the total charset size *or* the length of the largest keyword if the user specifies the -k'*' (ALLCHARS) option. This change cleans up client code. * Merged all the cperf changes into gperf. * Made sure to explicitly initialize perfect.fewest_collisions to 0. * Cleaned up some loose ends noticed by Nels Olson. 1. Removed `if (collisions <= perfect.fewest_collisions)' from Gen_Perf::affects_prev since it was superfluous. 2. Removed the fields best_char_value and best_asso_value from Gen_Perf. There were also unnecessary. 3. Fixed a braino in the Bool_Array::bool_array_reset function. Since iteration numbers can never be zero the `if (bool_array.iteration_number++ == 0)' must be `if (++bool_array.iteration_number == 0).' 4. Modified Std_Err::report_error so that it correctly handles "%%". * It is important to note that -D no longer enables -S. There is a good reason for this change, which will become manifested in the next release... (suspense!). * Made some subtle changes to Key_List::print_switch so that if finally seems to work correctly. Needs more stress testing, however... * Made a major change to the Key_List::print_switch function. The user can now specify the number of switch statements to generate via an argument to the -S option, i.e., -S1 means `generate 1 switch statement with all keywords in it,' -S2 means generate 2 switch statements with 1/2 the elements in each one, etc. Hopefully this will fix the problem with C compilers not being able to generate code for giant switch statements (but don't hold your breath!) * Changed Key_List::length function to Key_List::keyword_list_length. * Added a feature to main.c that prints out the starting wall-clock time before the program begins and prints out the ending wall-clock time when the program is finished. * Added the GATHER_STATISTICS code in hash-table.c so we can keep track of how well double hashing is doing. Eventually, GATHER_STATISTICS will be added so that all instrumentation code can be conditionally compiled in. * Fixed a stupid bug in Key_List::print_switch routine. This was necessary to make sure the generated switch statement worked correctly when *both* `natural,' i.e., static links and dynamic links, i.e., unresolved duplicates, hash to the same value. * Modified Bool_Array::~Bool_Array destructor so that it now frees the bool_array.storage_array when it is no longer needed. Since this array is generally very large it makes sense to return the memory to the freelist when it is no longer in use. * Changed the interface to constructor Hash_Table::Hash_Table. This constructor now passed a pointer to a power-of-two sized buffer that serve as storage for the hash table. Although this weakens information hiding a little bit it greatly reduces dynamic memory fragmentation, since we can now obtain the memory via a call to alloca, rather than malloc. This change modified Key_List::read_keys calling interface. * Since alloca is now being used more aggressively a conditional compilation section was added in main.c. Taken from GNU GCC, this code gets rid of any avoidable limit on stack size so that alloca does not fail. It is only used if the -DRLIMIT_STACK symbol is defined when gperf is compiled. * Added warnings in option.c so that user's would be informed that -r superceeds -i on the command-line. * Rewrote Gen_Perf::affects_prev. First, the code structure was cleaned up considerably (removing the need for a dreaded goto!). Secondly, a major change occurred so that Gen_Perf::affects_prev returns FALSE (success) when fewest_hits gets down to whatever it was after inserting the previous key (instead of waiting for it to reach 0). In other words, it stops trying if it can resolve the new collisions added by a key, even if there are still other old, unresolved collisions. This modification was suggested by Nels Olson and seems to *greatly* increase the speed of gperf for large keyfiles. Thanks Nels! * In a similar vein, inside the Gen_Perf::change routine the variable `perfect.fewest_collisions is no longer initialized with the length of the keyword list. Instead it starts out at 0 and is incremented by 1 every time change () is called. The rationale for this behavior is that there are times when a collision causes the number of duplicates (collisions) to increase by a large amount when it would presumably just have gone up by 1 if none of the asso_values were changed. That is, at the beginning of change(), you could initialize fewest_hits to 1+(previous value of fewest_hits) instead of to the number of keys. Thanks again, Nels. * Replaced alloca with new in the Gen_Perf::change function. This should eliminate some overhead at the expense of a little extra memory that is never reclaimed. * Renamed Gen_Perf::merge_sets to Gen_Perf::compute_disjoint_union to reflect the change in behavior. * Added the -e option so users can supply a string containing the characters used to separate keywords from their attributes. The default behavior is ",\n". * Removed the char *uniq_set field from LIST_NODE and modified uses of uniq_set in perfect.c and keylist.c. Due to changes to Gen_Perf::compute_disjoint_sets this field was no longer necessary, and its removal makes the program smaller and potentially faster. * Added lots of changes/fixes suggested by Nels Olson (umls.UUCP!olson@mis.ucsf.edu). In particular: 1. Changed Bool_Array so that it would dynamically create an array of unsigned shorts rather than ints if the LO_CAL symbol was defined during program compilation. This cuts the amount of dynamic memory usage in half, which is important for large keyfile input. 2. Added some additional debugging statements that print extra info to stderr when the -d option is enabled. 3. Fixed a really stupid bug in Key_List::print_switch A right paren was placed at the wrong location, which broke strlen (). 4. Fixed a subtle problem with printing case values when keylinks appear. The logic failed to account for the fact that there can be keylinks *and* regular node info also! 5. Changed the behavior of Key_List::read_keys so that it would honor -D unequivocally, i.e., it doesn't try to turn off dup handling if the user requests it, even if there are no immediate links in the keyfile input. 6. Modified the -j option so that -j 0 means `try random values when searching for a way to resolve collisions.' 7. Added a field `num_done' to the Gen_Perf struct. This is used to report information collected when trying to resolve hash collisions. 8. Modified the merge_sets algorithm to perform a disjoint union of two multisets. This ensures that subsequent processing in Gen_Perf::affect_prev doesn't waste time trying to change an associated value that is shared between two conflicting keywords. 9. Modified Gen_Perf::affects_prev so that it doesn't try random jump values unless the -j 0 option is enabled. 10. Fixed a silly bug in Gen_Perf::change. This problem caused gperf to seg fault when the -k* option was given and the keyfile file had long keywords. Sun Oct 29 00:18:55 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) * Modified class-specific new operations for Read_Line and List_Node so they don't fail if SIZE is larger than twice the previous buffer size. Note we double buffer size everytime the previous buffer runs out, as a heuristic to reduce future calls to malloc. Sun Oct 22 13:49:43 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Updated gperf version number to 2.0. Send to Doug Lea for incorporation into the long-awaited `official' libg++ 1.36 release! * Thanks to Nels Olson a silly bug in Gen_Perf::change () was fixed. This problem caused gperf to seg fault when the -k* option was given and the keyfile file had long keywords. * Modified Key_List::print_hash_function so that it output max_hash_value + 1 (rather than just max_hash_value) for any associated value entries that don't correspond to keyword charset characters. This should speed up rejection of non-keyword strings a little in some cases. Sat Oct 21 19:28:36 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Fixed Key_List::print_hash_function so that it no longer output things like `return 0 + ...' Although this probably gets optimized away by even the worst C compilers there isn't any point tempting fate... ;-) * Fixed class List_Node's constructor so that it wouldn't a priori refuse to consider trying to hash keys whose length is less than the smallest user-specified key position. It turns out this is not a problem unless the user also specifies the -n (NOLENGTH) option, in which case such keys most likely don't have a prayer of being hashed correctly! * Changed the name of the generated lookup table from `Hash_Table' to `asso_value' to be consistent with the gperf paper. Tue Oct 17 14:19:48 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added a flag GATHER_STATISTICS in the Makefile. If defined during compilation this turns on certain collection facilities that track the performance of gperf during its execution. In particular, I want to see how many collisions occur for the double hashing Hash_Table. * Added a safety check so that we don't screw up if the total number of `resets' of the Bool_Array exceeds MAX_INT. Since this number is around 2^31 it is unlikely that this would ever occur for most input, but why take the risk? * Changed the behavior for the -a (ANSI) option so that the generated prototypes use int rather than size_t for the LEN parameter. It was too ugly having to #include all over the place... Mon Oct 16 11:00:35 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Continued to work on the gperf paper for the USENIX C++ conference. At some point this will be merged back into the gperf documentation... Sat Oct 14 20:29:43 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) * Added a majorly neat hack to Bool_Array, suggested by rfg. The basic idea was to throw away the Ullman array technique. The Ullman array was used to remove the need to reinitialize all the Bool_Array elements to zero everytime we needed to determine whether there were duplicate hash values in the keyword list. The current trick uses an `iteration number' scheme, which takes about 1/3 the space and reduces the overall program running a time by about 20 percent for large input! The hack works as follows: 1. Dynamically allocation 1 boolean array of size k. 2. Initialize the boolean array to zeros, and consider the first iteration to be iteration 1. 2. Then on all subsequent iterations we `reset' the bool array by kicking the iteration count by 1. 3. When it comes time to check whether a hash value is currently in the boolean array we simply check its index location. If the value stored there is *not* equal to the current iteration number then the item is clearly *not* in the set. In that case we assign the iteration number to that array's index location for future reference. Otherwise, if the item at the index location *is* equal to the iteration number we've found a duplicate. No muss, no fuss! Mon Oct 2 12:30:54 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Changed some consts in options.h to enumerals, since g++ doesn't seem to like them at the moment! Sat Sep 30 12:55:24 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed a stupid bug in Key_List::print_hash_function that manifested itself if the `-k$' option was given (i.e., only use the key[length] character in the hash function). * Added support for the -C option. This makes the contents of all generated tables `readonly'. * Changed the handling of generated switches so that there is only one call to str[n]?cmp. This *greatly* reduces the size of the generated assembly code on all compilers I've seen. * Fixed a subtle bug that occurred when the -l and -S option was given. Code produced looked something like: if (len != key_len || !strcmp (s1, resword->name)) return resword; which doesn't make any sense. Clearly, this should be: if (len == key_len && !strcmp (s1, resword->name)) return resword; Tue Sep 26 10:36:50 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Changed class Read_Line's definition so that it no longer needs to know about the buffering scheme used to speed up dynamic memory allocation of input keywords and their associated attributes. This means that operator new is no longer a friend of Read_Line. Mon Sep 25 23:17:10 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Decided that Obstacks had too much overhead, so they were removed in favor of super-efficient, low-overhead buffered storage allocation hacks in Read_Line and List_Node. * No longer try to inline functions that g++ complains about (Key_List::Merge and Key_List::Merge_Sort). Sun Sep 24 13:11:24 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Changed classes Read_Line and List_Node to use Obstacks in order to cache memory allocation for keyword strings and List_Nodes. * Continued to experiment with inheritance schemes. * Added a new file `alpha.h', that declares static data shared (i.e., inherited) between classes List_Node and Key_List. Tue Sep 12 16:14:41 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Made numerous changes to incorporate multiple inheritance in gperf. Wed Aug 16 23:04:08 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added the -DCOMPILER_FIXED flag to the ./src/Makefile. This implies that people trying to compile gperf need to have a working version of the new g++ compiler (1.36.0). * Removed some extra spaces that were being added in the generated C code. Mon Jul 24 17:09:46 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed PRINT_HASH_FUNCTION and PRINT_LOOKUP_FUNCTION in keylist.c so that the generated functions take an unsigned int length argument. If -a is enabled the prototype is (const char *str, size_t len). Fri Jul 21 13:06:15 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed a typo in PRINT_KEYWORD_TABLE in keylist.cc that prevented the indentation from working correctly. * Fixed a horrible typo in PRINT_KEYWORD_TABLE in keylist.cc that prevented links from being printed correctly. Tue Jul 18 16:04:31 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed up readline.cc and readline.h so that they work OK with g++ compilers that aren't completely up-to-date. If symbol COMPILER_FIXED is defined then the behavior that works on my more recent version of g++ is enabled. Sun Jul 9 17:53:28 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Changed the ./tests subdirectory Makefile so that it uses $(CC) instead of gcc. Sun Jul 2 21:52:15 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed a number of subtle bugs that occurred when -S was combined with various and sundry options. * Added the -G option, that makes the generated keyword table a global static variable, rather than hiding it inside the lookup function. This allows other functions to directly access the contents in this table. * Added the "#" feature, that allows comments inside the keyword list from the input file. Comment handling takes place in readline.c. This simplifies the code and reduces the number of malloc calls. * Also added the -H option (user can give the name of the hash function) and the -T option (prevents the transfer of the type decl to the output file, which is useful if the type is already defined elsewhere). Thu Jun 22 20:39:39 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Modified many classes so that they would inherit Std_Err as a base class. This makes things more abstract... Fri Jun 16 14:23:00 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Modified the -f (FAST) option. This now takes an argument. The argument corresponds to the number of iterations used to resolve collisions. -f 0 uses the length of the keyword list (which is what -f did before). This makes life much easier when dealing with large keyword files. Tue Jun 6 17:53:27 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added the -c (comparison) option. Enabling this will use the strncmp function for string comparisons. The default is to use strcmp. * Fixed a typo in key_list.cc (PRINT_SWITCH). This caused faulty C code to be generated when the -D, -p, and -t options were all enabled. Thu May 25 14:07:21 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) * Once again, changed class Read_Line to overload global operator new. Hopefully, this will work...! Sun May 21 01:51:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Modified Key_List::print_hash_function () so that it properly formats the associated values in the hash table according to the maximum number of digits required to represent the largest value. * Removed the named return value from class Hash_Table's operator (), since this causes a seg fault when -O is enabled. No sense tripping subtle g++ bugs if we don't have to.... ;-) * Removed the operator new hack from Read_Line, since this seemed to create horrible bus error problems. * Changed many class member functions and data members to be `static', if they don't manipulate this! Fri May 12 23:06:56 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Changed class Std_Err to use static member functions, a la Ada or Modula 2. This eliminates the need for an explicit error-handler class object. * Added the ``named return value'' feature to Hash_Table::operator () and Bool_Array::operator [], just for the heck of it.... ;-) * Changed the previous hack in Read_Line so that we now use the overloaded global `new' instead of NEW_STRING! Wed May 3 17:36:55 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Updated to version 1.7. This reflects the recent major changes and the new C port. * Modified the GNU getopt.cc routine to have a class-based interface. * Fixed a typo in Perfect.cc ~Perfect that prevented the actual maximum hash table size from being printed (maybe the stream classes weren't so bad after all.... ;-). * Added support for the -f option. This generates the perfect hash function ``fast.'' It reduces the execution time of gperf, at the cost of minimizing the range of hash values. Tue May 2 16:23:29 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Added an efficiency hack to Read_Line. Instead of making a call to operator NEW (a.k.a. malloc) for each input string a new member function NEW_STRING stores a large buffer from which new strings are carved out, growing the buffer if necessary. It might be useful to add this throughout the program.... * Removed all unnecessary calls to DELETE. If the program is about to exit it is silly to waste time freeing memory. * Added the GNU getopt program to the distribution. This makes GPERF portable to systems that don't include getopt in libc. * Added a strcspn member to class Key_List. This also increases portability. * Added the get_include_src function from keylist.c as a member function in class Key_List. Hopefully every function is now associated with a class. This aids abstraction and modularity. * Ported gperf to C. From now on both K&R C and GNU G++ versions will be supported. There will be two ChangeLog files, one for each version of the program. Mon May 1 16:41:45 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed a bug with -k'*'. This now prints out *all* the cases up to the length of the longest word in the keyword set. Sun Apr 30 12:15:25 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Removed all use of the stream classes. Too ugly, slow, and not handled by the c++-mode formatter.... * Modified the handling of links (i.e., keywords that have identical hash values as other keywords). This should speed up hash function generation for keyword sets with many duplicate entries. The trick is to treat duplicate values as equivalence classes, so that each set of duplicate values is represented only once in the main list processing. * Fixed some capitialization typos and indentations mistakes in Key_List::print_hash_function. Sat Apr 29 12:04:03 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed a typo/logico in Key_List::print_switch that prevented the last keyword in the keyword list to be print out. This requires further examination..... * Fixed a stupid bug in List_Node::List_node. If the -k'*' option was enabled the KEY_SET string wasn't getting terminated with '\0'! Fri Apr 28 12:38:35 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Renamed strexp.h and strexp.cc to iterator.h and iterator.cc. Also changed the strexp class to iterator. Continued to work on style... * Updated the version number to 1.6. This reflects all the recent changes. Thu Apr 27 00:14:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added the -D option that properly handles keyword sets that contain duplicate hash values. * Continued the stylistic changes. Added the #pragma once directive to all the *.h files. Removed all #defines and replaced them with static consts. Also moved the key_sort routine from options.cc into the options class as a member function. Mon Apr 3 13:26:55 1989 Doug Schmidt (schmidt at zola.ics.uci.edu) * Made massive stylistic changes to bring source code into conformance with GNU style guidelines. Thu Mar 30 23:28:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Fixed up the output routines so that they generate code corresponding to the GNU style guidelines. Sat Mar 11 13:12:37 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed Stderr constructors so that they wouldn't try to use the base class initializer syntax for the static class variable Program_Name. G++ 1.34 is stricter in enforcing the rules! Fri Mar 10 11:24:14 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Removed -v and ``| more'' from the Makefile to keep rfg happy... Thu Mar 2 12:37:30 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Sent latest GNU gperf version 1.5 to Doug Lea for inclusion into libg++ 1.34. Note that there is a small bug with the new %{ ... %} source inclusion facility, since it doesn't understand comments and will barf if %{ or %} appear nested inside the outermost delimiters. This is too trivial of a defect to fix at the moment... Tue Feb 28 11:19:58 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added the -K option, which allows the user to provide a alternative name for the keyword structure component. The default is still ``name.'' * Added the LEX and YACC-like ability to include arbitrary text at the beginning of the generated C source code output. This required two new functions Get_Special_Input, Key_List::Save_Include_Src; * Fixed memory allocation bug in Key_List::Set_Types. Variable Return_Type needs 1 additional location to store the "*" if the -p option is used. * Added code to NULL terminate both Struct_Tag and Return_Type, *after* the strncpy (stupid mistake). Mon Feb 27 14:39:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added a new option -N. This allows the user to specify the name to be used for the generated lookup function. The default name is still ``in_word_set.'' This makes it possible to completely automate the perfect hash function generation process! Mon Feb 20 23:33:14 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Corrected the Hash_Table::operator () function so that *it* is responsible for deciding when a new key has the same signature as a previously seen key. The key length information is now used internally to this function to decide whether to add to the hash table those keys with the same key sets, but different lengths. Before, this was handled by the Key_List::Read_Keys function. However, this failed to work for certain duplicate keys, since they weren't being entered into the hash table properly. Sun Feb 19 16:02:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Modified class Options by moving the enum Option_Type out of the class. This is to satisfy the new enumeration scope rules in C++. Sun Jan 15 15:12:09 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Incremented the version number upto 1.4 to reflect the new options that affect the generated code. Send the new distribution off to Michael for use with g++ 1.33. * Added a fix to Key_List::Read_Keys so that it checks for links properly when the -n option is used. Previously, it didn't catch obvious links, which caused it to spend large amount of time searching for a solution that could never occur! * Modified the Key_List data structure to record *both* the minimum and the maximum key lengths. This information is now computed in Key_List::Read_Keys, and thus Key_List::Print_Min_Max doesn't need to bother. * Modifed the key position iterator scheme in options.cc to eliminate the need for member function Options::Advance. Now, the Options::Get function performs the advancement automatically, obviating the need for an extra function call. * Added the new function Options::Print_Options, to print out the user-specified command line options to generated C output file. * Added a new function, Key_List::Print_Keylength_Table, which creates a table of lengths for use in speeding up the keyword search. This also meant that a new option, -l (LENTABLE) is recognized. It controls whether the length table is printed and the comparison made in the generated function ``in_word_set.'' * Added a comment at the top of the generated C code output file that tells what version of gperf was used. Next, I'll also dump out the command line options as a comment too. Thanks to Michael Tiemann for the feedback on this. * Fixed the -n option to make it work correctly with other parts of the program (most notably the Perfect::Hash function and the computation of minimum and maximum lengths. Fri Jan 13 21:25:27 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) * Realized the the need to add a test that will enable optimziation of the generated C code in the ``hash'' function by checking whether all the requested key positions are guaranteed to exist due to the comparison in `in_word_set.'' I'll put this in soon.... Thu Jan 12 20:09:21 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Added pascal, modula3, and modula2 tests inputs to the Makefile * Recognised that there is a bug with the -n option. However I'm too busy to fix it properly, right now. The problem is that the generated #define end up being 0, since that's my hack to make -n work. This needs complete rethinking! Tue Jan 10 00:08:16 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Added a new option, -n, that instructs gperf to not use the length of an identifier when computing the hash functions. I'm not sure how useful this is! * Retransmitted the distribution to rocky.oswego.edu. Hopefully, this will work! * Began fixing the indentation and capitalization to conform to the GNU coding guidelines. Mon Jan 9 22:23:18 1989 Doug Schmidt (schmidt at pompe.ics.uci.edu) * Fixed horrible bug in Read_Line::Readln_Aux. This was a subtle and pernicous off-by-1 error, that overwrote past the last character of the input string buffer. I think this fault was killing the vax! * Yow, fixed an oversight in List_Node::List_Node, where the pointer field Next was uninitialized. Luckily, the new routine seems to return 0 filled objects the first time through! Sun Jan 8 13:43:14 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Modified the ``key linked'' diagnostic in Key_List::Read_Keys to be more helpful and easy to read. * Fixed the List_Node::List_Node so that it would ignore trailing fields if the -t option was not enabled. * Moved the List_Node declarations out of keylist.h and into a file of its own, called listnode.cc and listnode.h Made Set_Sort a member function of class List_Node. * Massively updated the documentation in the gperf.texinfo file. * Polished off the major revision to the print functions, added a few new tests in the Makefile to check for the validity of the program and ftp'ed the entire distribution off to Doug Lea for libg++. ( changed it to 1.3 to reflect the major changes with the generated C code ). * Fixed Key_List::Print_Switch to deal with the -p and -t options. This meant that the ``still-born'' function Key_List:: Print_Type_Switch was superflous, so I removed it. Also, removed the restriction in Option that the -p and -t options couldn't be used simultaneously. * Modified List_Node::List_Node, to perform only 1 call to ``new'' when dynamically allocating memory for the Key_Set and the Uniq_Set. Sat Jan 7 14:10:51 1989 Doug Schmidt (schmidt at glacier.ics.uci.edu) * Fixed a big bug with the new policy of nesting the wordlist inside of generated function ``in_word_set.'' I'd forgotten to declare the wordlist array as static! ( arrgh ). * Added a new function Key_List::Set_Types, that figures out the return type for generated function ``in_word_set,'' the user-defined ``struct tag,'' if one is used, and also formates the array type for the static local array. * Changed the print routines to take advantage of the new -p option. * Began adding the hooks to allow the return of a pointer to a user defined struct location from the generated ``in_word_set'' function instead of the current 0 or 1 return value. Created function Key_List::Print_Type_Switch and added option -p to class Option, allowing the user to request generation of the aforementioned pointers returned instead of booleans. * Put in checks in class Option to make sure that -S and -t options are not used simultaneously. This restriction will be removed in subsequent releases, once I decide on a clean way to implement it. * Sent version 1.2 to Doug Lea for possible inclusion into the libg++ distribution. * Moved the static word_list array inside the generated function in_word_set. This supports better data hiding. * Added a texinfo file, gperf.texinfo * Revised the Makefile to cleanup the droppings from texinfo and changed the name of gperf.cc and gperf.h to perfect.cc and perfect.h. Fri Jan 6 13:04:45 1989 Doug Schmidt (schmidt at crimee.ics.uci.edu) * Implemented the switch statement output format. Much better for large datasets in terms of space used. * Added new functions to break up the Key_List::Output function. Functions added were Key_List::Print_Switch, Key_List::Print_Min_Max, Key_List::Print_Keyword_Table, Key_List::Print_Hash_Function, and Key_List::Print_Lookup_Function. This simplifies the big mess in Key_List::Output considerably! * Added switch statement option to Options, which potentially trades time for space in the generated lookup code. Thu Jan 5 22:46:34 1989 Doug Schmidt (schmidt at siam.ics.uci.edu) * Released version 1.1 * Fixed a bug with Gperf::Merge_Set, it was skipping letters shared between the Set_1 and Set_2. * Added the optimal min/max algorithm in Key_List::Output. This runs in O ( 3n/2 ), rather than O ( 2n ) time. * Changed Gperf::Sort_Set to use insertion sort, rather than bubble sort. * Added a check in Key_List::Output for the special case where the keys used are 1,$. It is possible to generate more efficient C code in this case. d a bug with Gperf::Merge_Set, it was skipping letters shared between the Set_1 and Set_2. * Added the optimal min/max algorithm in Key_List::Output. This runs in O ( 3n/2 ), rather than O ( 2n ) time. * Changed Gperf::Sort_Set to use insertion sort, rather than bubble sort. * Added a check in Key_List::Output for libg++/gperf/gperf.texinfo 600 473 0 141215 4677677702 11014 \input texinfo @c -*-texinfo-*- @settitle User's Guide to @code{gperf} @setfilename gperf-info @ifinfo This file documents the features of the GNU Perfect Hash Function Generator Copyright (C) 1989 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 also that the section entitled ``GNU General Public License'' is included exactly as in the original, and 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 the section entitled ``GNU @code{gperf} General Public License'' an d this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English. @end ifinfo @setchapternewpage odd @titlepage @center @titlefont{User's Guide} @sp 2 @center @titlefont{for the} @sp 2 @center @titlefont{GNU GPERF Utility} @sp 4 @center Douglas C. Schmidt @sp 3 @center last updated 1 November 1989 @sp 1 @center for version 2.0 @page @vskip 0pt plus 1filll Copyright @copyright{} 1989 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 also that the section entitled ``GNU @code{gperf} General Public License'' is included exactl y as in the original, and 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 the section entitled ``GNU @code{gperf} General Public License'' ma y be included in a translation approved by the author instead of in the original English. @end titlepage @ifinfo @node Top, Copying, , (DIR) @ichapter Introduction This manual documents the GNU @code{gperf} perfect hash function generator utility, focusing on its features and how to use them, and how to report bugs. @end ifinfo @menu * Copying:: GNU @code{gperf} General Public License says how you can copy and share @code{gperf}. * Contributors:: People who have contributed to @code{gperf}. * Motivation:: Static search structures and GNU GPERF. * Description:: High-level discussion of how GPERF functions. * Options:: A description of options to the program. * Bugs:: Known bugs and limitations with GPERF. * Projects:: Things still left to do. * Implementation:: Implementation Details for GNU GPERF. * Bibliography:: Material Referenced in this Report. @end menu @node Copying, Contributors, Top, Top @unnumbered GNU GENERAL PUBLIC LICENSE @center Version 1, February 1989 @display Copyright @copyright{} 1989 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. @end display @unnumberedsec Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our 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. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 a 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 tell them 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. The precise terms and conditions for copying, distribution and modification follow. @iftex @unnumberedsec TERMS AND CONDITIONS @end iftex @ifinfo @center TERMS AND CONDITIONS @end ifinfo @enumerate @item This License Agreement 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 work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as ``you''. @item 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 General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. @item You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: @itemize @bullet @item cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and @item cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). @item If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual 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 General Public License. @item 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. @end itemize Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. @item You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: @itemize @bullet @item accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, @item accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, @item accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) @end itemize Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. @item You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. @item By copying, distributing or modifying 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. @item 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. @item 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 the 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 the license, you may choose any version ever published by the Free Software Foundation. @item 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. @iftex @heading NO WARRANTY @end iftex @ifinfo @center NO WARRANTY @end ifinfo @item 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. @item 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 enumerate @iftex @heading END OF TERMS AND CONDITIONS @end iftex @ifinfo @center END OF TERMS AND CONDITIONS @end ifinfo @page @unnumberedsec 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 humanity, 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. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) 19@var{yy} @var{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 1, 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. @end smallexample 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: @smallexample Gnomovision version 69, Copyright (C) 19@var{yy} @var{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. @end smallexample 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 a sample; alter the names: @example Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. @var{signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice @end example That's all there is to it! @node Contributors, Motivation, Copying, Top @unnumbered Contributors to GNU @code{gperf} Utility @itemize @bullet @item The GNU @code{gperf} perfect hash function generator utility was originally written in GNU C++ by Douglas C. Schmidt. It is now also available in a highly-portable ``old-style'' C version. The general idea for the perfect hash function generator was inspired by Keith Bostic's algorithm written in C, and distributed to net.sources around 1984. The current program is a heavily modified, enhanced, and extended implementation of Keith's basic idea, created at the University of California, Irvine. Bugs, patches, and suggestions should be reported to schmidt at ics.uci.edu. @item Special thanks is extended to Michael Tiemann and Doug Lea, for providing a useful compiler, and for giving me a forum to exhibit my creation. In addition, Adam de Boor and Nels Olson provided many tips and insights that greatly helped improve the quality and functionality of @code{gperf}. @end itemize @node Motivation, Search Structures, Contributors, Top @chapter Introduction @code{gperf} is a perfect hash function generator written in C++. It transforms an @emph{n} element user-specified keyword set @emph{W} into a perfect hash function @emph{F}. @emph{F} uniquely maps keywords in @emph{W} onto the range 0..@emph{k}, where @emph{k} >= @emph{n}. If @emph{k = n} then @emph{F} is a @emph{minimal} perfect hash function. @code{gperf} generates a 0..@emph{k} element static lookup table and a pair of C functions. These functions determine whether a given character string @emph{s} occurs in @emph{W}, using at most one probe into the lookup table. @code{gperf} currently generates the reserved keyword recognizer for lexical analyzers in several production and research compilers and language processing tools, including GNU C, GNU C++, GNU Pascal, GNU Modula 3, and GNU indent. Complete C++ source code for @code{gperf} is available via anonymous ftp from ics.uci.edu. @code{gperf} also is distributed along with the GNU libg++ library. Finally, a highly portable, functionally equivalent K&R C version of @code{gperf} is archived in comp.sources.unix, volume 20. @node Search Structures, Description, Motivation, Top @chapter Static search structures and GNU @code{gperf} A @dfn{static search structure} is an Abstract Data Type with certain fundamental operations, @emph{e.g.}, @emph{initialize}, @emph{insert}, and @emph{retrieve}. Conceptually, all insertions occur before any retrievals.@footnote{In practice, @code{gperf} generates a @code{static} array containing search set keywords and any associated attributes specified by the user. Thus, there is essentially no execution-time cost for the insertions.} It is a useful data structure for representing @emph{static search sets}. Static search sets occur frequently in software system applications. Typical static search sets include compiler reserved words, assembler instruction opcodes, and built-in shell interpreter commands. Search set members, called @dfn{keywords}, are inserted into the structure only once, usually during program initialization, and are not generally modified at run-time. Numerous static search structure implementations exist, @emph{e.g.}, arrays, linked lists, binary search trees, digital search tries, and hash tables. Different approaches offer trade-offs between space utilization and search time efficiency. For example, an @emph{n} element sorted array is space efficient, though the average-case time complexity for retrieval operations using binary search is proportional to log @emph{n}. Conversely, hash table implementations often locate a table entry in constant time, but typically impose additional memory overhead and exhibit poor worst case performance. @emph{Minimal perfect hash functions} provide an optimal solution for a particular class of static search sets. A minimal perfect hash function is defined by two properties: @itemize @bullet @item It allows keyword recognition in a static search set using at most @emph{one} probe into the hash table. This represents the ``perfect'' property. @item The actual memory allocated to store the keywords is precisely large enough for the keyword set, and @emph{no larger}. This is the ``minimal'' property. @end itemize For most applications it is far easier to generate @emph{perfect} hash functions than @emph{minimal perfect} hash functions. Moreover, non-minimal perfect hash functions frequently execute faster than minimal ones in practice. This phenomena occurs since searching a sparse keyword table increases the probability of locating a ``null'' entry, thereby reducing string comparisons. @code{gperf}'s default behavior generates @emph{near-minimal} perfect hash functions for keyword sets. However, @code{gperf} provides many options that permit user control over the degree of minimality and perfection. Static search sets often exhibit relative stability over time. For example, Ada's 63 reserved words have remained constant for nearly a decade. It is therefore frequently worthwhile to expend concerted effort building an optimal search structure @emph{once}, if it subsequently receives heavy use multiple times. @code{gperf} removes the drudgery associated with constructing time- and space-efficient search structures by hand. It has proven a useful and practical tool for serious programming projects. Output from @code{gperf} is currently used in several production and research compilers, including GNU C, GNU C++, GNU Pascal, and GNU Modula 3.@footnote{The latter two compilers are not yet part of the official GNU distr ibution.} Each compiler utilizes @code{gperf} to automatically generate static search structures that efficiently identify their respective reserved keywords. @node Description, Options, Motivation, Top @chapter High-Level Description of GNU @code{gperf} @menu * Input Format:: Input Format to @code{gperf} * Output Format:: Output Format for Generated C Code with @code{gperf} @end menu The perfect hash function generator @code{gperf} reads a set of ``keywords'' from a @dfn{keyfile} (or from the standard input by default). It attempts to derive a perfect hashing function that recognizes a member of the @dfn{static keyword set} with at most a single probe into the lookup table. If @code{gperf} succeeds in generating such a function it produces a pair of C source code routines that perform hashing and table lookup recognition. All generated C code is directed to the standard output. Command-line options described below allow you to modify the input and output format to @code{gperf}. By default, @code{gperf} attempts to produce time-efficient code, with less emphasis on efficient space utilization. However, several options exist that permit trading-off execution time for storage space and vice versa. In particular, expanding the generated table size produces a sparse search structure, generally yielding faster searches. Conversely, you can direct @code{gperf} to utilize a C @code{switch} statement scheme that minimizes data space storage size. Furthermore, using a C @code{switch} may actually speed up the keyword retrieval time somewhat. Actual results depend on your C compiler, of course. In general, @code{gperf} assigns values to the characters it is using for hashing until some set of values gives each keyword a unique value. A helpful heuristic is that the larger the hash value range, the easier it is for @code{gperf} to find and generate a perfect hash function. Experimentation is the key to getting the most from @code{gperf}. @node Input Format, Declarations, Description, Description @section Input Format to @code{gperf} You can control the input keyfile format by varying certain command-line arguments, in particular the @samp{-t} option. The input's appearance is similar to GNU utilities @code{flex} and @code{bison} (or UNIX utilities @code{lex} and @code{yacc}). Here's an outline of the general format: @group @example declarations %% keywords %% functions @end example @end group @emph{Unlike} @code{flex} or @code{bison}, all sections of @code{gperf}'s input are optional. The following sections describe the input format for each section. @menu * Declarations:: @code{struct} Declarations and C Code Inclusion. * Keywords:: Format for Keyword Entries. * Functions:: Including Additional C Functions. @end menu @node Declarations, Keywords, Input Format, Input Format @subsection @code{struct} Declarations and C Code Inclusion The keyword input file optionally contains a section for including arbitrary C declarations and definitions, as well as provisions for providing a user-supplied @code{struct}. If the @samp{-t} option @emph{is} enabled, you @emph{must} provide a C @code{struct} as the last component in the declaration section from the keyfile file. The first field in this struct must be a @code{char *} identifier called ``name,'' although it is possible to modify this field's name with the @samp{-K} option described below. Here is simple example, using months of the year and their attributes as input: @group @example struct months @{ char *name; int number; int days; int leap_days; @}; %% january, 1, 31, 31 february, 2, 28, 29 march, 3, 31, 31 april, 4, 30, 30 may, 5, 31, 31 june, 6, 30, 30 july, 7, 31, 31 august, 8, 31, 31 september, 9, 30, 30 october, 10, 31, 31 november, 11, 30, 30 december, 12, 31, 31 @end example @end group Separating the @code{struct} declaration from the list of key words and other fields are a pair of consecutive percent signs, @code{%%}, appearing left justified in the first column, as in the UNIX utility @code{lex}. Using a syntax similar to GNU utilities @code{flex} and @code{bison}, it is possible to directly include C source text and comments verbatim into the generated output file. This is accomplished by enclosing the region inside left-justified surrounding @code{%@{}, @code{%@}} pairs. Here is an input fragment based on the previous example that illustrates this feature: @group @example %@{ #include /* This section of code is inserted directly into the output. */ int return_month_days (struct months *months, int is_leap_year); %@} struct months @{ char *name; int number; int days; int leap_days; @}; %% january, 1, 31, 31 february, 2, 28, 29 march, 3, 31, 31 ... @end example @end group It is possible to omit the declaration section entirely. In this case the keyfile begins directly with the first keyword line, @emph{e.g.}: @group @example january, 1, 31, 31 february, 2, 28, 29 march, 3, 31, 31 april, 4, 30, 30 ... @end example @end group @node Keywords, Functions, Declarations, Input Format @subsection Format for Keyword Entries The second keyfile format section contains lines of keywords and any associated attributes you might supply. A line beginning with @samp{#} in the first column is considered a comment. Everything following the @samp{#} is ignored, up to and including the following newline. The first field of each non-comment line is always the key itself. It should be given as a simple name, @emph{i.e.}, without surrounding string quotation marks, and be left-justified flush against the first column. In this context, a ``field'' is considered to extend up to, but not include, the first blank, comma, or newline. Here is a simple example taken from a partial list of C reserved words: @group @example # These are a few C reserved words, see the c.@code{gperf} file # for a complete list of ANSI C reserved words. unsigned sizeof switch signed if default for while return @end example @end group Note that unlike @code{flex} or @code{bison} the first @code{%%} marker may be elided if the declaration section is empty. Additional fields may optionally follow the leading keyword. Fields should be separated by commas, and terminate at the end of line. What these fields mean is entirely up to you; they are used to initialize the elements of the user-defined @code{struct} provided by you in the declaration section. If the @samp{-t} option is @emph{not} enabled these fields are simply ignored. All previous examples except the last one contain keyword attributes. @node Functions, Output Format, Keywords, Input Format @subsection Including Additional C Functions The optional third section also corresponds closely with conventions found in @code{flex} and @code{bison}. All text in this section, starting at the final @code{%%} and extending to the end of the input file, is included verbatim into the generated output file. Naturally, it is your responsibility to ensure that the code contained in this section is valid C. @node Output Format, , Functions, Description @section Output Format for Generated C Code with @code{gperf} Several options control how the generated C code appears on the standard output. Two C function are generated. They are called @code{hash} and @code{in_word_set}, although you may modify the name for @code{in_word_set} with a command-line option. Both functions require two arguments, a string, @code{char *} @var{str}, and a length parameter, @code{int} @var{len}. Their default function prototypes are as follows: @group @example static int hash (char *str, int len); int in_word_set (char *str, int len); @end example @end group By default, the generated @code{hash} function returns an integer value created by adding @var{len} to several user-specified @var{str} key positions indexed into an @dfn{associated values} table stored in a local static array. The associated values table is constructed internally by @code{gperf} and later output as a static local C array called @var{hash_table}; its meaning and properties are described below. @xref{Implementation}. The relevant key positions are specified via the @samp{-k} option when running @code{gperf}, as detailed in the @emph{Options} section below. @xref{Options}. Two options, @samp{-g} (assume you are compiling with GNU C and its @code{inline} feature) and @samp{-a} (assume ANSI C-style function prototypes), alter the content of both the generated @code{hash} and @code{in_word_set} routines. However, function @code{in_word_set} may be modified more extensively, in response to your option settings. The options that affect the @code{in_word_set} structure are: @itemize @bullet @table @samp @item -p Have function @code{in_word_set} return a pointer rather than a boolean. @item -t Make use of the user-defined @code{struct}. @item -S @var{total switch statements} Generate 1 or more C @code{switch} statement rather than use a large, (and potentially sparse) static array. Although the exact time and space savings of this approach vary according to your C compiler's degree of optimization, this method often results in smaller and faster code. @end table @end itemize If the @samp{-t}, @samp{-S}, and @samp{-p} options are omitted the default action is to generate a @code{char *} array containing the keys, together with additional null strings used for padding the array. By experimenting with the various input and output options, and timing the resulting C code, you can determine the best option choices for different keyword set characteristics. @node Options, Bugs, Description, Top @chapter Options to the @code{gperf} Utility There are @emph{many} options to @code{gperf}. They were added to make the program more convenient for use with real applications. ``On-line'' help is readily available via the @samp{-h} option. Other options include: @itemize @bullet @table @samp @item -a Generate ANSI Standard C code using function prototypes. The default is to use ``classic'' K&R C function declaration syntax. @item -c Generates C code that uses the @code{strncmp} function to perform string comparisons. The default action is to use @code{strcmp}. @item -C Makes the contents of all generated lookup tables constant, @emph{i.e.}, ``readonly.'' Many compilers can generate more efficient code for this by putting the tables in readonly memory. @item -d Enables the debugging option. This produces verbose diagnostics to ``standard error'' when @code{gperf} is executing. It is useful both for maintaining the program and for determining whether a given set of options is actually speeding up the search for a solution. Some useful information is dumped at the end of the program when the @samp{-d} option is enabled. @item -D Handle keywords whose key position sets hash to duplicate values. Duplicate hash values occur for two reasons: @itemize @bullet @item Since @code{gperf} does not backtrack it is possible for it to process all your input keywords without finding a unique mapping for each word. However, frequently only a very small number of duplicates occur, and the majority of keys still require one probe into the table. @item Sometimes a set of keys may have the same names, but possess different attributes. With the -D option @code{gperf} treats all these keys as part of an equivalence class and generates a perfect hash function with multiple comparisons for duplicate keys. It is up to you to completely disambiguate the keywords by modifying the generated C code. However, @code{gperf} helps you out by organizing the output. @end itemize Option @samp{-D} is extremely useful for certain large or highly redundant keyword sets, @emph{i.e.}, assembler instruction opcodes. Using this option usually means that the generated hash function is no longer perfect. On the other hand, it permits @code{gperf} to work on keyword sets that it otherwise could not handle. @item -e @var{keyword delimiter list} Allows the user to provide a string containing delimiters used to separate keywords from their attributes. The default is ",\n". This option is essential if you want to use keywords that have embedded commas or newlines. One useful trick is to use -e'TAB', where TAB is the literal tab character. @item -f @var{iteration amount} Generate the perfect hash function ``fast.'' This decreases @code{gperf}'s running time at the cost of minimizing generated table-size. The iteration amount represents the number of times to iterate when resolving a collision. `0' means `iterate by the number of keywords. This option is probably most useful when used in conjunction with options @samp{-D} and/or @samp{-S} for @emph{large} keyword sets. @item -g Assume a GNU compiler, @emph{e.g.}, @code{g++} or @code{gcc}. This makes all generated routines use the ``inline'' keyword to remove the cost of function calls. Note that @samp{-g} does @emph{not} imply @samp{-a}, since other non-ANSI C compilers may have provisions for a function @code{inline} feature. @item -G Generate the static table of keywords as a static global variable, rather than hiding it inside of the lookup function (which is the default behavior). @item -h Prints a short summary on the meaning of each program option. Aborts further program execution. @item -H @var{hash function name} Allows you to specify the name for the generated hash function. Default name is `hash.' This option permits the use of two hash tables in the same file. @item -i @var{initial value} Provides an initial @var{value} for the associate values array. Default is 0. Increasing the initial value helps inflate the final table size, possibly leading to more time efficient keyword lookups. Note that this option is not particularly useful when @samp{-S} is used. Also, @samp{-i} is overriden when the @samp{-r} option is used. @item -j @var{jump value} Affects the ``jump value,'' @emph{i.e.}, how far to advance the associated character value upon collisions. @var{Jump value} is rounded up to an odd number, the default is 5. If the @var{jump value} is 0 @code{gper f} jumps by random amounts. @item -k @var{keys} Allows selection of the character key positions used in the keywords' hash function. The allowable choices range between 1-126, inclusive. The positions are separated by commas, @emph{e.g.}, @samp{-k 9,4,13,14}; ranges may be used, @emph{e.g.}, @samp{-k 2-7}; and positions may occur in any order. Furthermore, the meta-character '*' causes the generated hash function to consider @strong{all} character positions in each key, whereas '$' instructs the hash function to use the ``final character'' of a key (this is the only way to use a character position greater than 126, incidentally). For instance, the option @samp{-k 1,2,4,6-10,'$'} generates a hash function that considers positions 1,2,4,6,7,8,9,10, plus the last character in each key (which may differ for each key, obviously). Keys with length less than the indicated key positions work properly, since selected key positions exceeding the key length are simply not referenced in the hash function. @item -K @var{key name} By default, the program assumes the structure component identifier for the keyword is ``name.'' This option allows an arbitrary choice of identifier for this component, although it still must occur as the first field in your supplied @code{struct}. @item -l Compare key lengths before trying a string comparison. This might cut down on the number of string comparisons made during the lookup, since keys with different lengths are never compared via @code{strcmp}. However, using @samp{-l} might greatly increase the size of the generated C code if the lookup table range is large (which implies that the switch option @samp{-S} is not enabled), since the length table contains as many elements as there are entries in the lookup table. @item -L @var{generated language name} Instructs @code{gperf} to generate code in the language specified by the option's argument. Languages handled are currently C++ and C. The default is C. @item -n Instructs the generator not to include the length of a keyword when computing its hash value. This may save a few assembly instructions in the generated lookup table. @item -N @var{lookup function name} Allows you to specify the name for the generated lookup function. Default name is `in_word_set.' This option permits completely automatic generation of perfect hash functions, especially when multiple generated hash functions are used in the same application. Note that if -LC++ is enabled this option provides the name of the generated C++ class (since the name of the generated lookup member function is then @code{operator ()}). @item -o Reorders the keywords by sorting the keywords so that frequently occuring key position set components appear first. A second reordering pass follows so that keys with ``already determined values'' are placed towards the front of the keylist. This may decrease the time required to generate a perfect hash function for many keyword sets, and also produce more minimal perfect hash functions. The reason for this is that the reordering helps prune the search time by handling inevitable collisions early in the search process. On the other hand, if the number of keywords is @emph{very} large using @samp{-o} may @emph{increase} @code{gperf}'s execution time, since collisions will begin earlier and continue throughout the remainder of keyword processing. See Cichelli's paper from the January 1980 Communications of the ACM for details. @item -p Changes the return value of the generated function @code{in_word_set} from boolean (@emph{i.e.}, 0 or 1), to either type ``pointer to user-defined struct,'' (if the @samp{-t} option is enabled), or simply to @code{char *}, if @samp{-t} is not enabled. This option is most useful when the @samp{-t} option (allowing user-defined structs) is used. For example, it is possible to automatically generate the GNU C reserved word lookup routine with the options @samp{-p} and @samp{-t}. @item -r Utilizes randomness to initialize the associated values table. This frequently generates solutions faster than using deterministic initialization (which starts all associated values at 0). Furthermore, using the randomization option generally increases the size of the table. If @code{gperf} has difficultly with a certain keyword set try using @samp{-r} or @samp{-D}. @item -s @var{size-multiple} Affects the size of the generated hash table. The numeric argument for this option indicates ``how many times larger or smaller'' the maximum associated value range should be, in relationship to the number of keys. If the @var{size-multiple} is negative the maximum associated value is calculated by @emph{dividing} it into the total number of keys. For example, a value of 3 means ``allow the maximum associated value to be about 3 times larger than the number of input keys.'' Conversely, a value of -3 means ``allow the maximum associated value to be about 3 times smaller than the number of input keys.'' Negative values are useful for limiting the overall size of the generated hash table, though this usually increases the number of duplicate hash values. If `generate switch' option @samp{-S} is @emph{not} enabled, the maximum associated value influences the static array table size, and a larger table should decrease the time required for an unsuccessful search, at the expense of extra table space. The default value is 1, thus the default maximum associated value about the same size as the number of keys (for efficiency, the maximum associated value is always rounded up to a power of 2). The actual table size may vary somewhat, since this technique is essentially a heuristic. In particular, setting this value too high slows down @code{gperf}'s runtime, since it must search through a much larger range of values. Judicious use of the @samp{-f} option helps alleviate this overhead, however. @item -S @var{total switch statements} Causes the generated C code to use a @code{switch} statement scheme, rather than an array lookup table. This can lead to a reduction in both time and space requirements for some keyfiles. The argument to this option determines how many @code{switch} statements are generated. A value of 1 generates 1 @code{switch} containing all the elements, a value of 2 generates 2 tables with 1/2 the elements in each @code{switch}, etc. This is useful since many C compilers cannot correctly generate code for large @code{switch} statements. This option was inspired in part by Keith Bostic's original C program. @item -t Allows you to include a @code{struct} type declaration for generated code. Any text before a pair of consecutive %% is consider part of the type declaration. Key words and additional fields may follow this, one group of fields per line. A set of examples for generating perfect hash tables and functions for Ada, C, and G++, Pascal, and Modula 2 and 3 reserved words are distributed with this release. @item -T Prevents the transfer of the type declaration to the output file. Use this option if the type is already defined elsewhere. @item -v Prints out the current version number. @end table @end itemize @node Bugs, Projects, Options, Top @chapter Known Bugs and Limitations with @code{gperf} The following are some limitations with the current release of @code{gperf}: @itemize @bullet @item The @code{gperf} utility is tuned to execute quickly, and works quickly for small to medium size data sets (around 1000 keywords). It is extremely useful for maintaining perfect hash functions for compiler keyword sets. Several recent enhancements now enable @code{gperf} to work efficiently on much larger keyword sets (over 15,000 keywords). When processing large keyword sets it helps greatly to have over 8 megs of RAM. However, since @code{gperf} does not backtrack no guaranteed solution occurs on every run. On the other hand, it is usually easy to obtain a solution by varying the option parameters. In particular, try the @samp{-r} option, and also try changing the default arguments to the @samp{-s} and @samp{-j} options. To @emph{guarantee} a solution, use the @samp{-D} and @samp{-S} options, although the final results are not likely to be a @emph{perfect} hash function anymore! Finally, use the @samp{-f} option if you want @code{gperf} to generate the perfect hash function @emph{fast}, with less emphasis on making it minimal. @item The size of the generate static keyword array can get @emph{extremely} large if the input keyword file is large or if the keywords are quite similar. This tends to slow down the compilation of the generated C code, and @emph{greatly} inflates the object code size. If this situation occurs, consider using the @samp{-S} option to reduce data size, potentially increasing keyword recognition time a negligible amount. Since many C compilers cannot correctly generated code for large switch statements it is important to qualify the @var{-S} option with an appropriate numerical argument that controls the number of switch statements generated. @item The maximum number of key positions selected for a given key has an arbitrary limit of 126. This restriction should be removed, and if anyone considers this a problem write me and let me know so I can remove the constraint. @item The C++ source code only compiles correctly with GNU G++, version 1.36 (and hopefully later versions). Porting to AT&T cfront would be tedious, but possible (and desirable). There is also a K&R C version available now. This should compile without change on most BSD systems, but may require a bit of work to run on SYSV, since @code{gperf} uses @var{alloca} in several places. Send mail to schmidt at ics.uci.edu for information. @end itemize @node Projects, Implementation, Bugs, Top @chapter Things Still Left to Do It should be ``relatively'' easy to replace the current perfect hash function algorithm with a more exhaustive approach; the perfect hash module is essential independent from other program modules. Additional worthwhile improvements include: @itemize @bullet @item Make the algorithm more robust. At present, the program halts with an error diagnostic if it can't find a direct solution and the @samp{-D} option is not enabled. A more comprehensive, albeit computationally expensive, approach would employ backtracking or enable alternative options and retry. It's not clear how helpful this would be, in general, since most search sets are rather small in practice. @item Another useful extension involves modifying the program to generate ``minimal'' perfect hash functions (under certain circumstances, the current version can be rather extravagant in the generated table size). Again, this is mostly of theoretical interest, since a sparse table often produces faster lookups, and use of the @samp{-S} @code{switch} option can minimize the data size, at the expense of slightly longer lookups (note that the gcc compiler generally produces good code for @code{switch} statements, reducing the need for more complex schemes). @item In addition to improving the algorithm, it would also be useful to generate a C++ class or Ada package as the code output, in addition to the current C routines. @end itemize @node Implementation, Bibliography, Projects, Top @chapter Implementation Details of GNU @code{gperf} A paper describing the high-level description of the data structures and algorithms used to implement @code{gperf} will soon be available. This paper is useful not only from a maintenance and enhancement perspective, but also because they demonstrate several clever and useful programming techniques, @emph{e.g.}, `Iteration Number' boolean arrays, double hashing, a ``safe'' and efficient method for reading arbitrarily long input from a file, and a provably optimal algorithm for simultaneously determining both the minimum and maximum elements in a list. @page @node Bibliography, , Implementation, Top @chapter Bibliography [1] Chang, C.C.: @i{A Scheme for Constructing Ordered Minimal Perfect Hashing Functions} Information Sciences 39(1986), 187-195. [2] Cichelli, Richard J. @i{Author's Response to ``On Cichelli's Minimal Perfec t Hash Functions Method''} Communications of the ACM, 23, 12(December 1980), 729. [3] Cichelli, Richard J. @i{Minimal Perfect Hash Functions Made Simple} Communications of the ACM, 23, 1(January 1980), 17-19. [4] Cook, C. R. and Oldehoeft, R.R. @i{A Letter Oriented Minimal Perfect Hashing Function} SIGPLAN Notices, 17, 9(September 1982), 18-27. [5] Cormack, G. V. and Horspool, R. N. S. and Kaiserwerth, M. @i{Practical Perfect Hashing} Computer Journal, 28, 1(January 1985), 54-58. [6] Jaeschke, G. @i{Reciprocal Hashing: A Method for Generating Minimal Perfect Hashing Functions} Communications of the ACM, 24, 12(December 1981), 829-833. [7] Jaeschke, G. and Osterburg, G. @i{On Cichelli's Minimal Perfect Hash Functions Method} Communications of the ACM, 23, 12(December 1980), 728-729. [8] Sager, Thomas J. @i{A Polynomial Time Generator for Minimal Perfect Hash Functions} Communications of the ACM, 28, 5(December 1985), 523-532 [9] Sebesta, R.W. and Taylor, M.A. @i{Minimal Perfect Hash Functions for Reserved Word Lists} SIGPLAN Notices, 20, 12(September 1985), 47-53. [10] Sprugnoli, R. @i{Perfect Hashing Functions: A Single Probe Retrieving Method for Static Sets} Communications of the ACM, 20 11(November 1977), 841-850. [11] Stallman, Richard M. @i{Using and Porting GNU CC} Free Software Foundation , 1988. [12] Stroustrup, Bjarne @i{The C++ Programming Language.} Addison-Wesley, 1986. [13] Tiemann, Michael D. @i{User's Guide to GNU C++} Free Software Foundation, 1989. @contents @bye nctions for Reserved Word Lists} SIGPLAN Notices, 20, 12(September 1985), 47-53. [10] Sprugnoli, R. @i{Perfect Hashing Functions: A Single Probe Retrieving Method for Static Sets} Communications of the ACM, 20 11(November 1977), 841-850. [11] Stallman, Richard M. @i{Using and Porting GNU CC} Free Software Foundation , 1988. [12] Stroustrup, Bjarne @i{The C++ Progralibg++/gperf/tests/adadefs.gperf 644 473 0 731 4677677702 12016 boolean character constraint_error false float integer natural numeric_error positive program_error storage_error string tasking_error true address aft base callable constrained count delta digits emax epsilon first firstbit fore image large last lastbit length machine_emax machine_emin machine_mantissa machine_overflows machine_radix machine_rounds mantissa pos position pred range safe_emax safe_large safe_small size small storage_size succ terminated val value width libg++/gperf/tests/c++.gperf 644 473 0 460 4677677702 10776 asm auto break case catch char class const continue default delete do double else enum extern float for friend goto if inline int long new operator overload private protected public register return short signed sizeof static struct switch template this typedef union unsigned virtual void volatile while machine_overflows machine_radix machine_rounds mantissa pos position pred range safe_emax safe_large safe_small size small storage_size succ terminated val value width libg++/gperf/tests/gpc.gperf 644 473 0 2142 4677677702 11216 %{ /* ISO Pascal 7185 reserved words. * * For GNU Pascal compiler (GPC) by jtv@hut.fi * * run this through the Doug Schmidt's gperf program * with command * gperf -g -o -j1 -t -p -N is_reserved_word * */ %} struct resword { char *name; short token; short iclass;}; %% And, AND, PASCAL_ISO Array, ARRAY, PASCAL_ISO Begin, BEGIN_, PASCAL_ISO Case, CASE, PASCAL_ISO Const, CONST, PASCAL_ISO Div, DIV, PASCAL_ISO Do, DO, PASCAL_ISO Downto, DOWNTO, PASCAL_ISO Else, ELSE, PASCAL_ISO End, END, PASCAL_ISO File, FILE_, PASCAL_ISO For, FOR, PASCAL_ISO Function, FUNCTION, PASCAL_ISO Goto, GOTO, PASCAL_ISO If, IF, PASCAL_ISO In, IN, PASCAL_ISO Label, LABEL, PASCAL_ISO Mod, MOD, PASCAL_ISO Nil, NIL, PASCAL_ISO Not, NOT, PASCAL_ISO Of, OF, PASCAL_ISO Or, OR, PASCAL_ISO Packed, PACKED, PASCAL_ISO Procedure, PROCEDURE, PASCAL_ISO Program,PROGRAM,PASCAL_ISO Record, RECORD, PASCAL_ISO Repeat, REPEAT, PASCAL_ISO Set, SET, PASCAL_ISO Then, THEN, PASCAL_ISO To, TO, PASCAL_ISO Type, TYPE, PASCAL_ISO Until, UNTIL, PASCAL_ISO Var, VAR, PASCAL_ISO While, WHILE, PASCAL_ISO With, WITH, PASCAL_ISO PASCAL_ISO If, IF, PASCAL_ISO In, IN, PASCAL_ISO Label, LABEL, PASCAL_ISO Mod, MOD, PASCAL_ISO Nil, NIL, PASCAL_ISO Not, NOT, PASCAL_ISO Of, OF, PASCAL_ISO Or, OR, PASCAL_ISO Packed, PACKED, PASCAL_ISO Procedure, PROCEDURE, PASCAL_ISO Program,PROGRAM,PASCAL_ISO Record, RECORD, PASCAL_ISO Repeat, REPEAT, PASCAL_ISO Set, SET, PASCAL_ISO Then, THEN, PASCAL_ISO To, TO, PASCAL_ISO Type, TYPE, PASCAL_ISO Unlibg++/gperf/tests/makeinfo.gperf 644 473 0 5701 4677677703 12243 COMMAND; %% !, cm_force_sentence_end, false ', insert_self, false *, cm_asterisk, false ., cm_force_sentence_end, false :, cm_force_abbreviated_whitespace, false ?, cm_force_sentence_end, false @, insert_self, false TeX, cm_TeX, true `, insert_self, false appendix, cm_appendix, false appendixsec, cm_appendixsec, false appendixsubsec, cm_appendixsubsec, false asis, cm_asis, true b, cm_bold, true br, cm_br, false bullet, cm_bullet, true bye, cm_bye, false c, cm_comment, false center, cm_center, false chapter, cm_chapter, false cindex, cm_cindex, false cite, cm_cite, true code, cm_code, true comment, cm_comment, false contents, do_nothing, false copyright, cm_copyright, true ctrl, cm_ctrl, true defcodeindex, cm_defindex, false defindex, cm_defindex, false dfn, cm_dfn, true display, cm_display, false dots, cm_dots, true emph, cm_emph, true end, cm_end, false enumerate, cm_enumerate, false equiv, cm_equiv, true error, cm_error, true example, cm_example, false exdent, cm_exdent, false expansion, cm_expansion, true file, cm_file, true findex, cm_findex, false format, cm_format, false group, cm_group, false i, cm_italic, true iappendix, cm_appendix, false iappendixsec, cm_appendixsec, false iappendixsubsec, cm_appendixsubsec, false ichapter, cm_chapter, false ifinfo, cm_ifinfo, false iftex, cm_iftex, false ignore, cm_ignore, false include, cm_include, false inforef, cm_inforef, true input, cm_include, false isection, cm_section, false isubsection, cm_subsection, false isubsubsection, cm_subsubsection, false item, cm_item, false itemize, cm_itemize, false itemx, cm_itemx, false iunnumbered, cm_unnumbered, false iunnumberedsec, cm_unnumberedsec, false iunnumberedsubsec, cm_unnumberedsubsec, false kbd, cm_kbd, true key, cm_key, true kindex, cm_kindex, false lisp, cm_lisp, false menu, cm_menu minus, cm_minus, true need, cm_need, false node, cm_node, false noindent, cm_noindent, false page, do_nothing, false pindex, cm_pindex, false point, cm_point, true print, cm_print, true printindex, cm_printindex, false pxref, cm_pxref, true quotation, cm_quotation, false r, cm_roman, true ref, cm_xref, true refill, cm_refill, false result, cm_result, true samp, cm_samp, true sc, cm_sc, true section, cm_section, false setchapternewpage, cm_setchapternewpage, false setfilename, cm_setfilename, false settitle, cm_settitle, false smallexample, cm_smallexample, false sp, cm_sp, false strong, cm_strong, true subsection, cm_subsection, false subsubsection, cm_subsubsection, false summarycontents, do_nothing, false syncodeindex, cm_synindex, false synindex, cm_synindex, false t, cm_title, true table, cm_table, false tex, cm_tex, false tindex, cm_tindex, false titlepage, cm_titlepage, false unnumbered, cm_unnumbered, false unnumberedsec, cm_unnumberedsec, false unnumberedsubsec, cm_unnumberedsubsec, false var, cm_var, true vindex, cm_vindex, false w, cm_w, true xref, cm_xref, true {, insert_self, false }, insert_self, false infoinclude, cm_infoinclude, false footnote, cm_footnote, false marycontents, do_nothing, false syncodeindex, cm_synindex, falslibg++/gperf/tests/Makefile 644 473 0 6142 4677677703 11065 # Copyright (C) 1989 Free Software Foundation, Inc. # written by Douglas C. Schmidt (schmidt@ics.uci.edu) # # This file is part of GNU GPERF. # # GNU GPERF 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 1, or (at your option) # any later version. # # GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. SHELL = /bin/sh GPERF = ../gperf CC = gcc CFLAGS = -O all: test test: @echo "performing some tests of the perfect hash generator" $(CC) -c $(CFLAGS) test.c $(GPERF) -p -c -l -S1 -C -o c.gperf > cinset.c $(CC) $(CFLAGS) -o cout cinset.c test.o @echo "testing ANSI C reserved words, all items should be found in the set" ./cout -v < c.gperf > output.c -diff -b expected.c output.c $(GPERF) -k1,4,'$$' ada.gperf > adainset.c # double '$$' is only there since make gets confused; program wants only 1 '$' $(CC) $(CFLAGS) -o aout adainset.c test.o @echo "testing Ada reserved words,all items should be found in the set" ./aout -v < ada.gperf > output.ada-res -diff -b expected.ada-res output.ada-res $(GPERF) -p -D -k1,'$$' -s 2 -o adadefs.gperf > preinset.c $(CC) $(CFLAGS) -o preout preinset.c test.o @echo "testing Ada predefined words, all items should be found in the set" ./preout -v < adadefs.gperf > output.ada-pred -diff -b expected.ada-pred output.ada-pred $(GPERF) -k1,2,'$$' -o modula3.gperf > m3inset.c $(CC) $(CFLAGS) -o m3out m3inset.c test.o @echo "testing Modula3 reserved words, all items should be found in the set" ./m3out -v < modula3.gperf > output.modula -diff -b expected.modula output.modula $(GPERF) -o -S2 -p < pascal.gperf > pinset.c $(CC) $(CFLAGS) -o pout pinset.c test.o @echo "testing Pascal reserved words, all items should be found in the set" ./pout -v < pascal.gperf > output.pascal -diff -b expected.pascal output.pascal # these next 5 are demos that show off the generated code $(GPERF) -p -j1 -g -o -t -N is_reserved_word -k1,3,'$$' c-parse.gperf > test.out.1 -diff -b expected.out.1 test.out.1 $(GPERF) -n -k1-8 -l modula2.gperf > test.out.2 -diff -b expected.out.2 test.out.2 $(GPERF) -p -j 1 -o -a -g -t -k1,4,$$ gplus.gperf > test.out.3 -diff -b expected.out.3 test.out.3 $(GPERF) -D -p -t < c-parse.gperf > test.out.4 -diff -b expected.out.4 test.out.4 $(GPERF) -g -o -j1 -t -p -N is_reserved_word gpc.gperf > test.out.5 -diff -b expected.out.5 test.out.5 # prints out the help message -$(GPERF) -h > test.out.6 2>&1 -diff -b expected.out.6 test.out.6 @echo "only if, do, for, case, goto, else, while, and return should be found " ./aout -v < c.gperf > test.out.7 -diff -b expected.out.7 test.out.7 clean: -rm -f *.o core *~ *inset.c test.out.* *out #*# out.3 test.out.3 $(GPERF) -D -p -t < c-parse.gperf > test.out.4 -diff -b expected.out.4 test.out.4 $(GPERF) -g -o -j1 -t -p -N is_reserved_word gpc.gperf > test.out.5 -diff -b expected.out.5 test.out.5 # prints out the help message -$(GPERF) -h > test.out.6 2>&1 -diff -b expected.out.6 test.out.6 @echo "only if, do, for, case, goto, else, while, and return should be found " ./aout -v < c.gperf > test.oulibg++/gperf/tests/test.c 644 473 0 1034 4677677703 10543 /* Tests the generated perfect has function. The -v option prints diagnostics as to whether a word is in the set or not. Without -v the program is useful for timing. */ #include #define MAX_LEN 80 int main (argc, argv) int argc; char *argv[]; { int verbose = argc > 1 ? 1 : 0; char buf[MAX_LEN]; while (gets (buf)) if (in_word_set (buf, strlen (buf)) && verbose) printf ("in word set %s\n", buf); else if (verbose) printf ("NOT in word set %s\n", buf); return 0; } rfect has function. The -v option prints diagnostics as to whether a word is in the set or not. Without -v the program is useful for timing. */ #include #define MAX_LEN 80 int main (argc, argv) int argc; char *argv[]; { int verbose = argc > 1 ? 1 : 0; char buf[MAX_LEN]; while (gets (buf)) if (in_word_set (buf, strlen (buf)) && verbose) printf ("in word set %s\n", buf); else if (verbose) printf ("NOT in word set libg++/gperf/tests/pascal.gperf 644 473 0 274 4677677703 11675 with array and function case var const until then set record program procedure or packed not nil label in repeat of goto forward for while file else downto do div to type end mod begin if lude #define MAX_LEN 80 int main (argc, argv) int argc; char *argv[]; { int verbose = argc > 1 ? 1 : 0; char buf[MAX_LEN]; while (gets (buf)) if (in_word_set (buf, strlen (buf)) && verbose) printf ("in word set %s\n", buf); else if (verbose) printf ("NOT in word set libg++/gperf/tests/modula3.gperf 644 473 0 1140 4677677703 12007 AND ARRAY BEGIN BITS BY CASE CONST DIV DO ELSE ELSIF END EVAL EXCEPT EXCEPTION EXIT EXPORTS FINALLY FOR FROM IF IMPORT INTERFACE IN INLINE LOCK METHODS MOD MODULE NOT OBJECT OF OR PROCEDURE RAISES READONLY RECORD REF REPEAT RETURN SET THEN TO TRY TYPE TYPECASE UNSAFE UNTIL UNTRACED VALUE VAR WHILE WITH and array begin bits by case const div do else elsif end eval except exception exit exports finally for from if import interface in inline lock methods mod module not object of or procedure raises readonly record ref repeat return set then to try type typecase unsafe until untraced value var while with LLY FOR FROM IF IMPORT INTERFACE IN INLINE LOCK METHODS MOD MODULE NOT OBJECT OF OR PROCEDURE RAISES READONLY RECORD REF REPEAT RETURN SET THEN TO TRY TYPE TYPECASE UNSAFE UNTIL UNTRACED VALUE VAR WHILE WITH and array begin bits by case const div do else elsif end eval except exception exit exports finally for from if import interface in inline lock methods mod module not object of or procedure raises readonly relibg++/gperf/tests/modula2.gperf 644 473 0 341 4677677703 11770 AND ARRAY BEGIN BY CASE CONST DEFINITION DIV DO ELSE ELSIF END EXIT EXPORT FOR FROM IF IMPLEMENTATION IMPORT IN LOOP MOD MODULE NOT OF OR POINTER PROCEDURE QUALIFIED RECORD REPEAT RETURN SET THEN TO TYPE UNTIL VAR WHILE WITH ETURN SET THEN TO TRY TYPE TYPECASE UNSAFE UNTIL UNTRACED VALUE VAR WHILE WITH and array begin bits by case const div do else elsif end eval except exception exit exports finally for from if import interface in inline lock methods mod module not object of or procedure raises readonly relibg++/gperf/tests/gplus.gperf 644 473 0 4030 4677677704 11577 %{ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf */ %} struct resword { char *name; short token; enum rid rid;}; %% __alignof, ALIGNOF, NORID __alignof__, ALIGNOF, NORID __asm, ASM, NORID __asm__, ASM, NORID __attribute, ATTRIBUTE, NORID __attribute__, ATTRIBUTE, NORID __const, TYPE_QUAL, RID_CONST __const__, TYPE_QUAL, RID_CONST __inline, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE __signed, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED __typeof, TYPEOF, NORID __typeof__, TYPEOF, NORID __volatile, TYPE_QUAL, RID_VOLATILE __volatile__, TYPE_QUAL, RID_VOLATILE all, ALL, NORID /* Extension */, except, EXCEPT, NORID /* Extension */, exception, AGGR, RID_EXCEPTION /* Extension */, raise, RAISE, NORID /* Extension */, raises, RAISES, NORID /* Extension */, reraise, RERAISE, NORID /* Extension */, try, TRY, NORID /* Extension */, asm, ASM, NORID, auto, SCSPEC, RID_AUTO, break, BREAK, NORID, case, CASE, NORID, catch, CATCH, NORID, char, TYPESPEC, RID_CHAR, class, AGGR, RID_CLASS, const, TYPE_QUAL, RID_CONST, continue, CONTINUE, NORID, default, DEFAULT, NORID, delete, DELETE, NORID, do, DO, NORID, double, TYPESPEC, RID_DOUBLE, dynamic, DYNAMIC, NORID, else, ELSE, NORID, enum, ENUM, NORID, extern, SCSPEC, RID_EXTERN, float, TYPESPEC, RID_FLOAT, for, FOR, NORID, friend, SCSPEC, RID_FRIEND, goto, GOTO, NORID, if, IF, NORID, inline, SCSPEC, RID_INLINE, int, TYPESPEC, RID_INT, long, TYPESPEC, RID_LONG, new, NEW, NORID, operator, OPERATOR, NORID, overload, OVERLOAD, NORID, private, PRIVATE, NORID, protected, PROTECTED, NORID, public, PUBLIC, NORID, register, SCSPEC, RID_REGISTER, return, RETURN, NORID, short, TYPESPEC, RID_SHORT, signed, TYPESPEC, RID_SIGNED, sizeof, SIZEOF, NORID, static, SCSPEC, RID_STATIC, struct, AGGR, RID_RECORD, switch, SWITCH, NORID, this, THIS, NORID, typedef, SCSPEC, RID_TYPEDEF, typeof, TYPEOF, NORID, union, AGGR, RID_UNION, unsigned, TYPESPEC, RID_UNSIGNED, virtual, SCSPEC, RID_VIRTUAL, void, TYPESPEC, RID_VOID, volatile, TYPE_QUAL, RID_VOLATILE, while, WHILE, NORID, RID, protected, PROTECTED, NORID, public, PUBLIC, NORID, register, SCSPEC, RID_REGISTER, return, RETURN, NORID, short, TYPESPEC, RID_SHORT, signed, TYPESPEC, RID_SIGNED, sizeof, SIZEOF, NORID, static, SCSPEC, RID_STATIC, struct, AGGR, RID_RECORD, switch, SWITCH, NORID, this, THIS, NORID, typedef, SCSPEC, RID_TYPEDEF, typeof, TYPEOF, NORID, union, AGGR, RID_UNION, unsigned, TYPESPEC, RID_UNSIGNED, virtual, SCSPEC, RID_VIRTUAL, void, TYPESPEC, RID_VOID, volatile, TYPE_QUAL, RID_VOLATILlibg++/gperf/tests/c.gperf 644 473 0 306 4677677704 10651 if do int for case char auto goto else long void enum float short union break while const double static extern struct return sizeof switch signed typedef default unsigned continue register volatile of, SIZEOF, NORID, static, SCSPEC, RID_STATIC, struct, AGGR, RID_RECORD, switch, SWITCH, NORID, this, THIS, NORID, typedef, SCSPEC, RID_TYPEDEF, typeof, TYPEOF, NORID, union, AGGR, RID_UNION, unsigned, TYPESPEC, RID_UNSIGNED, virtual, SCSPEC, RID_VIRTUAL, void, TYPESPEC, RID_VOID, volatile, TYPE_QUAL, RID_VOLATILlibg++/gperf/tests/c-parse.gperf 644 473 0 2644 4677677704 12010 %{ /* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ %} struct resword { char *name; short token; enum rid rid; }; %% __alignof, ALIGNOF, NORID __alignof__, ALIGNOF, NORID __asm, ASM, NORID __asm__, ASM, NORID __attribute, ATTRIBUTE, NORID __attribute__, ATTRIBUTE, NORID __const, TYPE_QUAL, RID_CONST __const__, TYPE_QUAL, RID_CONST __inline, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE __signed, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED __typeof, TYPEOF, NORID __typeof__, TYPEOF, NORID __volatile, TYPE_QUAL, RID_VOLATILE __volatile__, TYPE_QUAL, RID_VOLATILE asm, ASM, NORID auto, SCSPEC, RID_AUTO break, BREAK, NORID case, CASE, NORID char, TYPESPEC, RID_CHAR const, TYPE_QUAL, RID_CONST continue, CONTINUE, NORID default, DEFAULT, NORID do, DO, NORID double, TYPESPEC, RID_DOUBLE else, ELSE, NORID enum, ENUM, NORID extern, SCSPEC, RID_EXTERN float, TYPESPEC, RID_FLOAT for, FOR, NORID goto, GOTO, NORID if, IF, NORID inline, SCSPEC, RID_INLINE int, TYPESPEC, RID_INT long, TYPESPEC, RID_LONG register, SCSPEC, RID_REGISTER return, RETURN, NORID short, TYPESPEC, RID_SHORT signed, TYPESPEC, RID_SIGNED sizeof, SIZEOF, NORID static, SCSPEC, RID_STATIC struct, STRUCT, NORID switch, SWITCH, NORID typedef, SCSPEC, RID_TYPEDEF typeof, TYPEOF, NORID union, UNION, NORID unsigned, TYPESPEC, RID_UNSIGNED void, TYPESPEC, RID_VOID volatile, TYPE_QUAL, RID_VOLATILE while, WHILE, NORID OAT for, FOR, NORID goto, GOTO, NORID if, IF, NORID inline, SCSPEC, RID_INLINE int, TYPESPEClibg++/gperf/tests/ada.gperf 644 473 0 556 4677677704 11163 else exit terminate type raise range reverse declare end record exception not then return separate select digits renames subtype elsif function for package procedure private while when new entry delay case constant at abort accept and delta access abs pragma array use out do others of or all limited loop null task in is if rem mod begin body xor goto generic with volatile, TYPE_QUAL, RID_VOLATILE while, WHILE, NORID OAT for, FOR, NORID goto, GOTO, NORID if, IF, NORID inline, SCSPEC, RID_INLINE int, TYPESPEClibg++/gperf/tests/output.ada-res 600 473 0 2142 4677677704 12210 in word set else in word set exit in word set terminate in word set type in word set raise in word set range in word set reverse in word set declare in word set end in word set record in word set exception in word set not in word set then in word set return in word set separate in word set select in word set digits in word set renames in word set subtype in word set elsif in word set function in word set for in word set package in word set procedure in word set private in word set while in word set when in word set new in word set entry in word set delay in word set case in word set constant in word set at in word set abort in word set accept in word set and in word set delta in word set access in word set abs in word set pragma in word set array in word set use in word set out in word set do in word set others in word set of in word set or in word set all in word set limited in word set loop in word set null in word set task in word set in in word set is in word set if in word set rem in word set mod in word set begin in word set body in word set xor in word set goto in word set generic in word set with at in word set abort in word set accept in word set and in word set delta in word set access in word set abs in word set pragma in word set array in word set use in word set out in word set do in word set others in word set of in word set or in word set all in word set limited in word set loop in word set null in word set task in word set in in word set is in word set if in word set rem in word set mod in wordlibg++/gperf/tests/expected.ada-p 600 473 0 2141 4677677705 12117 in word set boolean in word set character in word set constraint_error in word set false in word set float in word set integer in word set natural in word set numeric_error in word set positive in word set program_error in word set storage_error in word set string in word set tasking_error in word set true in word set address in word set aft in word set base in word set callable in word set constrained in word set count in word set delta in word set digits in word set emax in word set epsilon in word set first in word set firstbit in word set fore in word set image in word set large in word set last in word set lastbit in word set length in word set machine_emax in word set machine_emin in word set machine_mantissa in word set machine_overflows in word set machine_radix in word set machine_rounds in word set mantissa in word set pos in word set position in word set pred in word set range in word set safe_emax in word set safe_large in word set safe_small in word set size in word set small in word set storage_size in word set succ in word set terminated in word set val in word set value in word set width word set lastbit in word set length in word set machine_emax in word set machine_emin in word set machine_mantissa in word set machine_overflows in word set machine_radix in word set machine_rounds in word set mantissa in word set pos in word set position in word set pred in word set range in word set safe_emax in word set safe_large in word set safe_small in word set size in word set small in word set storage_libg++/gperf/tests/output.c 600 473 0 1106 4677677705 11116 in word set if in word set do in word set int in word set for in word set case in word set char in word set auto in word set goto in word set else in word set long in word set void in word set enum in word set float in word set short in word set union in word set break in word set while in word set const in word set double in word set static in word set extern in word set struct in word set return in word set sizeof in word set switch in word set signed in word set typedef in word set default in word set unsigned in word set continue in word set register in word set volatile set case in word set char in word set auto in word set goto in word set else in word set long in word set void in word set enum in word set float in word set short in word set union in word set break in word set while in word set const in word set double in word set static in word set extern in word set struct in word set return in word set sizeof in word set switch in word set signed in word set typedef in word set default in word set unlibg++/gperf/tests/expected.ada-r 600 473 0 2142 4677677705 12122 in word set else in word set exit in word set terminate in word set type in word set raise in word set range in word set reverse in word set declare in word set end in word set record in word set exception in word set not in word set then in word set return in word set separate in word set select in word set digits in word set renames in word set subtype in word set elsif in word set function in word set for in word set package in word set procedure in word set private in word set while in word set when in word set new in word set entry in word set delay in word set case in word set constant in word set at in word set abort in word set accept in word set and in word set delta in word set access in word set abs in word set pragma in word set array in word set use in word set out in word set do in word set others in word set of in word set or in word set all in word set limited in word set loop in word set null in word set task in word set in in word set is in word set if in word set rem in word set mod in word set begin in word set body in word set xor in word set goto in word set generic in word set with at in word set abort in word set accept in word set and in word set delta in word set access in word set abs in word set pragma in word set array in word set use in word set out in word set do in word set others in word set of in word set or in word set all in word set limited in word set loop in word set null in word set task in word set in in word set is in word set if in word set rem in word set mod in wordlibg++/gperf/tests/expected.c 600 473 0 1106 4677677705 11357 in word set if in word set do in word set int in word set for in word set case in word set char in word set auto in word set goto in word set else in word set long in word set void in word set enum in word set float in word set short in word set union in word set break in word set while in word set const in word set double in word set static in word set extern in word set struct in word set return in word set sizeof in word set switch in word set signed in word set typedef in word set default in word set unsigned in word set continue in word set register in word set volatile set case in word set char in word set auto in word set goto in word set else in word set long in word set void in word set enum in word set float in word set short in word set union in word set break in word set while in word set const in word set double in word set static in word set extern in word set struct in word set return in word set sizeof in word set switch in word set signed in word set typedef in word set default in word set unlibg++/gperf/tests/expected.modul 600 473 0 3530 4677677706 12261 in word set AND in word set ARRAY in word set BEGIN in word set BITS in word set BY in word set CASE in word set CONST in word set DIV in word set DO in word set ELSE in word set ELSIF in word set END in word set EVAL in word set EXCEPT in word set EXCEPTION in word set EXIT in word set EXPORTS in word set FINALLY in word set FOR in word set FROM in word set IF in word set IMPORT in word set INTERFACE in word set IN in word set INLINE in word set LOCK in word set METHODS in word set MOD in word set MODULE in word set NOT in word set OBJECT in word set OF in word set OR in word set PROCEDURE in word set RAISES in word set READONLY in word set RECORD in word set REF in word set REPEAT in word set RETURN in word set SET in word set THEN in word set TO in word set TRY in word set TYPE in word set TYPECASE in word set UNSAFE in word set UNTIL in word set UNTRACED in word set VALUE in word set VAR in word set WHILE in word set WITH in word set and in word set array in word set begin in word set bits in word set by in word set case in word set const in word set div in word set do in word set else in word set elsif in word set end in word set eval in word set except in word set exception in word set exit in word set exports in word set finally in word set for in word set from in word set if in word set import in word set interface in word set in in word set inline in word set lock in word set methods in word set mod in word set module in word set not in word set object in word set of in word set or in word set procedure in word set raises in word set readonly in word set record in word set ref in word set repeat in word set return in word set set in word set then in word set to in word set try in word set type in word set typecase in word set unsafe in word set until in word set untraced in word set value in word set var in word set while in word set with set inline in word set lock in word set methods in word set mod in word set module in word set not in word set object in word set of in word set or in word set procedurlibg++/gperf/tests/expected.out.1 644 473 0 10074 4677677706 12140 /* C code produced by gperf version 2.3 (GNU C++ version) */ /* Command-line: ../gperf -p -j1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ /* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ struct resword { char *name; short token; enum rid rid; }; #define TOTAL_KEYWORDS 51 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 13 #define MIN_HASH_VALUE 8 #define MAX_HASH_VALUE 82 /* maximum key range = 75, duplicates = 0 */ #ifdef __GNUC__ inline #endif static unsigned int hash (str, len) register char *str; register int unsigned len; { static unsigned char asso_values[] = { 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 83, 1, 2, 34, 19, 6, 11, 29, 0, 17, 83, 0, 23, 28, 26, 30, 31, 83, 15, 1, 0, 28, 13, 4, 83, 83, 5, 83, 83, 83, 83, 83, }; register int hval = len; switch (hval) { default: case 3: hval += asso_values[str[2]]; case 2: case 1: hval += asso_values[str[0]]; } return hval + asso_values[str[len - 1]]; } #ifdef __GNUC__ inline #endif struct resword * is_reserved_word (str, len) register char *str; register unsigned int len; { static struct resword wordlist[] = { {"__asm__", ASM, NORID}, {"",}, {"__typeof__", TYPEOF, NORID}, {"__signed__", TYPESPEC, RID_SIGNED}, {"__alignof__", ALIGNOF, NORID}, {"break", BREAK, NORID}, {"__attribute__", ATTRIBUTE, NORID}, {"",}, {"",}, {"else", ELSE, NORID}, {"__attribute", ATTRIBUTE, NORID}, {"__typeof", TYPEOF, NORID}, {"int", TYPESPEC, RID_INT}, {"__alignof", ALIGNOF, NORID}, {"struct", STRUCT, NORID}, {"sizeof", SIZEOF, NORID}, {"switch", SWITCH, NORID}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"",}, {"__inline__", SCSPEC, RID_INLINE}, {"__signed", TYPESPEC, RID_SIGNED}, {"__volatile", TYPE_QUAL, RID_VOLATILE}, {"if", IF, NORID}, {"__inline", SCSPEC, RID_INLINE}, {"while", WHILE, NORID}, {"",}, {"__asm", ASM, NORID}, {"auto", SCSPEC, RID_AUTO}, {"short", TYPESPEC, RID_SHORT}, {"default", DEFAULT, NORID}, {"extern", SCSPEC, RID_EXTERN}, {"",}, {"",}, {"__const", TYPE_QUAL, RID_CONST}, {"static", SCSPEC, RID_STATIC}, {"__const__", TYPE_QUAL, RID_CONST}, {"for", FOR, NORID}, {"case", CASE, NORID}, {"float", TYPESPEC, RID_FLOAT}, {"return", RETURN, NORID}, {"typeof", TYPEOF, NORID}, {"typedef", SCSPEC, RID_TYPEDEF}, {"volatile", TYPE_QUAL, RID_VOLATILE}, {"do", DO, NORID}, {"inline", SCSPEC, RID_INLINE}, {"void", TYPESPEC, RID_VOID}, {"char", TYPESPEC, RID_CHAR}, {"signed", TYPESPEC, RID_SIGNED}, {"unsigned", TYPESPEC, RID_UNSIGNED}, {"",}, {"",}, {"double", TYPESPEC, RID_DOUBLE}, {"asm", ASM, NORID}, {"",}, {"",}, {"goto", GOTO, NORID}, {"",}, {"const", TYPE_QUAL, RID_CONST}, {"enum", ENUM, NORID}, {"register", SCSPEC, RID_REGISTER}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"continue", CONTINUE, NORID}, {"",}, {"union", UNION, NORID}, {"",}, {"",}, {"",}, {"",}, {"",}, {"long", TYPESPEC, RID_LONG}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register char *s = wordlist[key].name; if (*s == *str && !strcmp (str + 1, s + 1)) return &wordlist[key]; } } return 0; } INUE, NORID}, {"",}, {"union", UNION, NORID}, {"",}, {"",}, {"",}, {"",}, {"",}, {"long", TYPESPEC, RID_LONG}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register char *s = wordlist[key].name; if (*s == *str && !strcmp (str + 1, s + 1)) libg++/gperf/tests/output.ada-pre 600 473 0 2141 4677677713 12204 in word set boolean in word set character in word set constraint_error in word set false in word set float in word set integer in word set natural in word set numeric_error in word set positive in word set program_error in word set storage_error in word set string in word set tasking_error in word set true in word set address in word set aft in word set base in word set callable in word set constrained in word set count in word set delta in word set digits in word set emax in word set epsilon in word set first in word set firstbit in word set fore in word set image in word set large in word set last in word set lastbit in word set length in word set machine_emax in word set machine_emin in word set machine_mantissa in word set machine_overflows in word set machine_radix in word set machine_rounds in word set mantissa in word set pos in word set position in word set pred in word set range in word set safe_emax in word set safe_large in word set safe_small in word set size in word set small in word set storage_size in word set succ in word set terminated in word set val in word set value in word set width word set lastbit in word set length in word set machine_emax in word set machine_emin in word set machine_mantissa in word set machine_overflows in word set machine_radix in word set machine_rounds in word set mantissa in word set pos in word set position in word set pred in word set range in word set safe_emax in word set safe_large in word set safe_small in word set size in word set small in word set storage_libg++/gperf/tests/expected.out.2 644 473 0 11746 4677677714 12147 /* C code produced by gperf version 2.3 (GNU C++ version) */ /* Command-line: ../gperf -n -k1-8 -l modula2.gperf */ #define TOTAL_KEYWORDS 40 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 14 #define MIN_HASH_VALUE 1 #define MAX_HASH_VALUE 256 /* maximum key range = 256, duplicates = 0 */ static unsigned int hash (str, len) register char *str; register int unsigned len; { static unsigned short asso_values[] = { 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 25, 30, 35, 21, 0, 30, 15, 30, 45, 257, 257, 0, 5, 45, 0, 10, 0, 1, 20, 25, 15, 30, 40, 15, 5, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, }; register int hval = 0; switch (len) { default: case 8: hval += asso_values[str[7]]; case 7: hval += asso_values[str[6]]; case 6: hval += asso_values[str[5]]; case 5: hval += asso_values[str[4]]; case 4: hval += asso_values[str[3]]; case 3: hval += asso_values[str[2]]; case 2: hval += asso_values[str[1]]; case 1: hval += asso_values[str[0]]; } return hval; } char * in_word_set (str, len) register char *str; register unsigned int len; { static unsigned char lengthtable[] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 0, 2, 3, 0, 0, 0, 2, 3, 0, 0, 0, 2, 4, 0, 0, 0, 4, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 3, 5, 6, 0, 0, 6, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 9, 0, 4, 6, 6, 0, 0, 2, 3, 0, 0, 0, 5, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, }; static char *wordlist[] = { "OR", "", "", "", "", "", "", "", "", "LOOP", "", "", "", "", "", "", "", "", "", "ELSE", "DO", "", "", "", "TO", "MOD", "", "", "", "OF", "FOR", "", "", "", "BY", "FROM", "", "", "", "TYPE", "MODULE", "", "", "", "SET", "", "", "", "", "", "EXPORT", "", "", "", "", "VAR", "ARRAY", "RECORD", "", "", "REPEAT", "", "", "", "", "END", "", "", "", "NOT", "", "", "", "", "IF", "", "", "", "", "CASE", "", "", "PROCEDURE", "", "EXIT", "IMPORT", "RETURN", "", "", "IN", "AND", "", "", "", "ELSIF", "DIV", "", "", "", "THEN", "", "", "", "", "", "", "", "", "", "IMPLEMENTATION", "", "", "", "", "WHILE", "", "", "", "", "", "", "", "", "", "CONST", "POINTER", "", "", "", "UNTIL", "", "", "", "", "BEGIN", "", "", "", "", "WITH", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "QUALIFIED", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "DEFINITION", }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register char *s = wordlist[key]; if (len == lengthtable[key] && *s == *str && !strcmp (str + 1, s + 1)) return s; } } return 0; } "", "", "", "", "", "", libg++/gperf/tests/expected.out.3 644 473 0 12626 4677677714 12146 /* C code produced by gperf version 2.3 (GNU C++ version) */ /* Command-line: ../gperf -p -j 1 -o -a -g -t -k1,4,$ gplus.gperf */ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf */ struct resword { char *name; short token; enum rid rid;}; #define TOTAL_KEYWORDS 71 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 13 #define MIN_HASH_VALUE 4 #define MAX_HASH_VALUE 147 /* maximum key range = 144, duplicates = 0 */ #ifdef __GNUC__ inline #endif static unsigned int hash (register const char *str, register int len) { static unsigned char asso_values[] = { 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 0, 148, 19, 6, 27, 37, 0, 12, 1, 15, 63, 148, 4, 0, 56, 20, 15, 42, 148, 31, 5, 26, 39, 32, 10, 148, 40, 148, 148, 148, 148, 148, 148, }; register int hval = len; switch (hval) { default: case 4: hval += asso_values[str[3]]; case 3: case 2: case 1: hval += asso_values[str[0]]; } return hval + asso_values[str[len - 1]]; } #ifdef __GNUC__ inline #endif struct resword * in_word_set (register const char *str, register int len) { static struct resword wordlist[] = { {"else", ELSE, NORID,}, {"",}, {"long", TYPESPEC, RID_LONG,}, {"",}, {"",}, {"",}, {"",}, {"__alignof__", ALIGNOF, NORID}, {"__asm__", ASM, NORID}, {"",}, {"",}, {"while", WHILE, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"__alignof", ALIGNOF, NORID}, {"all", ALL, NORID /* Extension */,}, {"sizeof", SIZEOF, NORID,}, {"__const__", TYPE_QUAL, RID_CONST}, {"__volatile", TYPE_QUAL, RID_VOLATILE}, {"extern", SCSPEC, RID_EXTERN,}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"__inline", SCSPEC, RID_INLINE}, {"exception", AGGR, RID_EXCEPTION /* Extension */,}, {"__inline__", SCSPEC, RID_INLINE}, {"case", CASE, NORID,}, {"except", EXCEPT, NORID /* Extension */,}, {"new", NEW, NORID,}, {"break", BREAK, NORID,}, {"goto", GOTO, NORID,}, {"",}, {"__attribute", ATTRIBUTE, NORID}, {"",}, {"__attribute__", ATTRIBUTE, NORID}, {"this", THIS, NORID,}, {"raise", RAISE, NORID /* Extension */,}, {"class", AGGR, RID_CLASS,}, {"delete", DELETE, NORID,}, {"typeof", TYPEOF, NORID,}, {"typedef", SCSPEC, RID_TYPEDEF,}, {"for", FOR, NORID,}, {"raises", RAISES, NORID /* Extension */,}, {"__const", TYPE_QUAL, RID_CONST}, {"double", TYPESPEC, RID_DOUBLE,}, {"__typeof__", TYPEOF, NORID}, {"",}, {"switch", SWITCH, NORID,}, {"auto", SCSPEC, RID_AUTO,}, {"do", DO, NORID,}, {"friend", SCSPEC, RID_FRIEND,}, {"",}, {"reraise", RERAISE, NORID /* Extension */,}, {"",}, {"volatile", TYPE_QUAL, RID_VOLATILE,}, {"__typeof", TYPEOF, NORID}, {"continue", CONTINUE, NORID,}, {"float", TYPESPEC, RID_FLOAT,}, {"const", TYPE_QUAL, RID_CONST,}, {"static", SCSPEC, RID_STATIC,}, {"virtual", SCSPEC, RID_VIRTUAL,}, {"__asm", ASM, NORID}, {"short", TYPESPEC, RID_SHORT,}, {"signed", TYPESPEC, RID_SIGNED,}, {"try", TRY, NORID /* Extension */,}, {"",}, {"",}, {"",}, {"__signed__", TYPESPEC, RID_SIGNED}, {"catch", CATCH, NORID,}, {"public", PUBLIC, NORID,}, {"struct", AGGR, RID_RECORD,}, {"if", IF, NORID,}, {"asm", ASM, NORID,}, {"union", AGGR, RID_UNION,}, {"",}, {"private", PRIVATE, NORID,}, {"",}, {"",}, {"",}, {"operator", OPERATOR, NORID,}, {"",}, {"",}, {"",}, {"default", DEFAULT, NORID,}, {"dynamic", DYNAMIC, NORID,}, {"overload", OVERLOAD, NORID,}, {"int", TYPESPEC, RID_INT,}, {"char", TYPESPEC, RID_CHAR,}, {"",}, {"",}, {"return", RETURN, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"__signed", TYPESPEC, RID_SIGNED}, {"",}, {"void", TYPESPEC, RID_VOID,}, {"",}, {"",}, {"",}, {"protected", PROTECTED, NORID,}, {"",}, {"enum", ENUM, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"inline", SCSPEC, RID_INLINE,}, {"register", SCSPEC, RID_REGISTER,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"unsigned", TYPESPEC, RID_UNSIGNED,}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register char *s = wordlist[key].name; if (*s == *str && !strcmp (str + 1, s + 1)) return &wordlist[key]; } } return 0; } {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"unsiglibg++/gperf/tests/expected.out.4 644 473 0 11106 4677677714 12137 /* C code produced by gperf version 2.3 (GNU C++ version) */ /* Command-line: ../gperf -D -p -t */ /* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */ struct resword { char *name; short token; enum rid rid; }; #define TOTAL_KEYWORDS 51 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 13 #define MIN_HASH_VALUE 4 #define MAX_HASH_VALUE 82 /* maximum key range = 79, duplicates = 2 */ static unsigned int hash (str, len) register char *str; register int unsigned len; { static unsigned char asso_values[] = { 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 83, 40, 20, 50, 25, 10, 30, 0, 0, 50, 83, 0, 15, 0, 35, 0, 83, 83, 20, 0, 10, 40, 5, 15, 83, 83, 83, 83, 83, 83, 83, 83, }; return len + asso_values[str[len - 1]] + asso_values[str[0]]; } struct resword * in_word_set (str, len) register char *str; register unsigned int len; { static struct resword wordlist[] = { {"goto", GOTO, NORID}, {"__asm", ASM, NORID}, {"switch", SWITCH, NORID}, {"__asm__", ASM, NORID}, {"__const__", TYPE_QUAL, RID_CONST}, {"__inline__", SCSPEC, RID_INLINE}, {"__typeof__", TYPEOF, NORID}, {"__signed__", TYPESPEC, RID_SIGNED}, {"__alignof__", ALIGNOF, NORID}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"__attribute__", ATTRIBUTE, NORID}, {"enum", ENUM, NORID}, {"short", TYPESPEC, RID_SHORT}, {"struct", STRUCT, NORID}, {"__const", TYPE_QUAL, RID_CONST}, {"__inline", SCSPEC, RID_INLINE}, {"long", TYPESPEC, RID_LONG}, {"__volatile", TYPE_QUAL, RID_VOLATILE}, {"__attribute", ATTRIBUTE, NORID}, {"volatile", TYPE_QUAL, RID_VOLATILE}, {"else", ELSE, NORID}, {"break", BREAK, NORID}, {"do", DO, NORID}, {"while", WHILE, NORID}, {"signed", TYPESPEC, RID_SIGNED}, {"__signed", TYPESPEC, RID_SIGNED}, {"void", TYPESPEC, RID_VOID}, {"sizeof", SIZEOF, NORID}, {"__typeof", TYPEOF, NORID}, {"__alignof", ALIGNOF, NORID}, {"double", TYPESPEC, RID_DOUBLE}, {"default", DEFAULT, NORID}, {"asm", ASM, NORID}, {"auto", SCSPEC, RID_AUTO}, {"float", TYPESPEC, RID_FLOAT}, {"typeof", TYPEOF, NORID}, {"typedef", SCSPEC, RID_TYPEDEF}, {"register", SCSPEC, RID_REGISTER}, {"extern", SCSPEC, RID_EXTERN}, {"for", FOR, NORID}, {"static", SCSPEC, RID_STATIC}, {"return", RETURN, NORID}, {"int", TYPESPEC, RID_INT}, {"case", CASE, NORID}, {"const", TYPE_QUAL, RID_CONST}, {"inline", SCSPEC, RID_INLINE}, {"continue", CONTINUE, NORID}, {"unsigned", TYPESPEC, RID_UNSIGNED}, {"char", TYPESPEC, RID_CHAR}, {"union", UNION, NORID}, {"if", IF, NORID}, }; static char lookup[] = { 0, 1, 2, 3, -1, 4, 69, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, 19, 20, 21, -1, 22, -5, -3, 23, 24, -1, 25, 26, -1, 27, -1, 28, 29, -1, 30, 31, 32, 33, 34, 35, 36, 37, -1, -1, 38, -1, 39, -1, -1, 40, -1, -1, -1, -1, 41, -1, 42, 43, 44, 45, -1, 46, -1, -1, -1, -1, 47, 48, -1, -1, -1, -1, -1, 49, -1, 50, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register int index = lookup[key]; if (index >= 0 && index < TOTAL_KEYWORDS) { register char *s = wordlist[index].name; if (*s == *str && !strcmp (str + 1, s + 1)) return &wordlist[key]; } else if (index < 0 && index >= -TOTAL_KEYWORDS) return 0; else { register int offset = key + index + (index > 0 ? -TOTAL_KEYWORDS : TOTAL_KEYWORDS); register struct resword *base = &wordlist[-lookup[offset]]; register struct resword *ptr = base + -lookup[offset + 1]; while (--ptr >= base) if (*str == *ptr->name && !strcmp (str + 1, ptr->name + 1)) return ptr; } } } return 0; } && index >= -TOTAL_KEYWORDS) return 0; else { register int offset = key + index + (index > 0 ? -TOTAL_KEYWORDS : TOTAL_KEYWORDS); register struct resword *base = &wordlist[-lookup[offset]]; register struct resword *ptr = base + -lookup[offset + 1]; while (--ptr >= base) if (*str == *ptr->name && !strcmp (str + 1, ptr->name + 1)) libg++/gperf/tests/output.modula 600 473 0 3530 4677677714 12160 in word set AND in word set ARRAY in word set BEGIN in word set BITS in word set BY in word set CASE in word set CONST in word set DIV in word set DO in word set ELSE in word set ELSIF in word set END in word set EVAL in word set EXCEPT in word set EXCEPTION in word set EXIT in word set EXPORTS in word set FINALLY in word set FOR in word set FROM in word set IF in word set IMPORT in word set INTERFACE in word set IN in word set INLINE in word set LOCK in word set METHODS in word set MOD in word set MODULE in word set NOT in word set OBJECT in word set OF in word set OR in word set PROCEDURE in word set RAISES in word set READONLY in word set RECORD in word set REF in word set REPEAT in word set RETURN in word set SET in word set THEN in word set TO in word set TRY in word set TYPE in word set TYPECASE in word set UNSAFE in word set UNTIL in word set UNTRACED in word set VALUE in word set VAR in word set WHILE in word set WITH in word set and in word set array in word set begin in word set bits in word set by in word set case in word set const in word set div in word set do in word set else in word set elsif in word set end in word set eval in word set except in word set exception in word set exit in word set exports in word set finally in word set for in word set from in word set if in word set import in word set interface in word set in in word set inline in word set lock in word set methods in word set mod in word set module in word set not in word set object in word set of in word set or in word set procedure in word set raises in word set readonly in word set record in word set ref in word set repeat in word set return in word set set in word set then in word set to in word set try in word set type in word set typecase in word set unsafe in word set until in word set untraced in word set value in word set var in word set while in word set with set inline in word set lock in word set methods in word set mod in word set module in word set not in word set object in word set of in word set or in word set procedurlibg++/gperf/tests/expected.out.5 644 473 0 6321 4677677714 12123 /* C code produced by gperf version 2.3 (GNU C++ version) */ /* Command-line: ../gperf -g -o -j1 -t -p -N is_reserved_word gpc.gperf */ /* ISO Pascal 7185 reserved words. * * For GNU Pascal compiler (GPC) by jtv@hut.fi * * run this through the Doug Schmidt's gperf program * with command * gperf -g -o -j1 -t -p -N is_reserved_word * */ struct resword { char *name; short token; short iclass;}; #define TOTAL_KEYWORDS 35 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 9 #define MIN_HASH_VALUE 2 #define MAX_HASH_VALUE 43 /* maximum key range = 42, duplicates = 0 */ #ifdef __GNUC__ inline #endif static unsigned int hash (str, len) register char *str; register int unsigned len; { static unsigned char asso_values[] = { 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 18, 29, 14, 6, 7, 10, 20, 44, 28, 44, 44, 28, 19, 22, 15, 0, 44, 9, 23, 0, 23, 26, 2, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 13, 44, 30, 44, 44, 44, 0, 25, 1, 0, 44, 44, 0, 44, 1, 44, 25, 44, 44, 0, 44, 44, 44, 44, 44, 44, }; return len + asso_values[str[len - 1]] + asso_values[str[0]]; } #ifdef __GNUC__ inline #endif struct resword * is_reserved_word (str, len) register char *str; register unsigned int len; { static struct resword wordlist[] = { {"To", TO, PASCAL_ISO}, {"",}, {"Type", TYPE, PASCAL_ISO}, {"Then", THEN, PASCAL_ISO}, {"Packed", PACKED, PASCAL_ISO}, {"While", WHILE, PASCAL_ISO}, {"Do", DO, PASCAL_ISO}, {"Procedure", PROCEDURE, PASCAL_ISO}, {"End", END, PASCAL_ISO}, {"Else", ELSE, PASCAL_ISO}, {"Downto", DOWNTO, PASCAL_ISO}, {"For", FOR, PASCAL_ISO}, {"File", FILE_, PASCAL_ISO}, {"Record", RECORD, PASCAL_ISO}, {"Repeat", REPEAT, PASCAL_ISO}, {"Or", OR, PASCAL_ISO}, {"Case", CASE, PASCAL_ISO}, {"Function", FUNCTION, PASCAL_ISO}, {"Const", CONST, PASCAL_ISO}, {"And", AND, PASCAL_ISO}, {"Mod", MOD, PASCAL_ISO}, {"Array", ARRAY, PASCAL_ISO}, {"Goto", GOTO, PASCAL_ISO}, {"Nil", NIL, PASCAL_ISO}, {"Not", NOT, PASCAL_ISO}, {"Set", SET, PASCAL_ISO}, {"Until", UNTIL, PASCAL_ISO}, {"Var", VAR, PASCAL_ISO}, {"Of", OF, PASCAL_ISO}, {"In", IN, PASCAL_ISO}, {"Program", PROGRAM,PASCAL_ISO}, {"Label", LABEL, PASCAL_ISO}, {"Div", DIV, PASCAL_ISO}, {"Begin", BEGIN_, PASCAL_ISO}, {"With", WITH, PASCAL_ISO}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"If", IF, PASCAL_ISO}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE - MIN_HASH_VALUE) && key >= 0) { register char *s = wordlist[key].name; if (*s == *str && !strcmp (str + 1, s + 1)) return &wordlist[key]; } } return 0; } BEGIN_, PASCAL_ISO}, {"With", WITH, PASCAL_ISO}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"If", IF, PASCAL_ISO}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash (str, len) - MIN_HASH_VALUE; if (key <= (MAX_HASH_VALUE -libg++/gperf/tests/expected.out.6 644 473 0 10656 4677677715 12153 /* starting time is 8:40:26 */ -a Generate ANSI standard C output code, i.e., function prototypes. -c Generate comparison code using strncmp rather than strcmp. -C Make the contents of generated lookup tables constant, i.e., readonly. -d Enables the debugging option (produces verbose output to the standard error). -D Handle keywords that hash to duplicate values. This is useful for certain highly redundant keyword sets. It enables the -S option. -e Allow user to provide a string containing delimiters used to separate keywords from their attributes. Default is ",\n" -f Generate the gen-perf.hash function ``fast.'' This decreases GPERF's running time at the cost of minimizing generated table-size. The numeric argument represents the number of times to iterate when resolving a collision. `0' means ``iterate by the number of keywords.'' -g Assume a GNU compiler, e.g., g++ or gcc. This makes all generated routines use the ``inline'' keyword to remove cost of function calls. -G Generate the static table of keywords as a static global variable, rather than hiding it inside of the lookup function (which is the default behavior). -h Prints this mesage. -H Allow user to specify name of generated hash function. Default is `hash'. -i Provide an initial value for the associate values array. Default is 0. Setting this value larger helps inflate the size of the final table. -j Affects the ``jump value,'' i.e., how far to advance the associated character value upon collisions. Must be an odd number, default is 5. -k Allows selection of the key positions used in the hash function. The allowable choices range between 1-126, inclusive. The positions are separated by commas, ranges may be used, and key positions may occur in any order. Also, the meta-character '*' causes the generated hash function to consider ALL key positions, and $ indicates the ``final character'' of a key, e.g., $,1,2,4,6-10. -K Allow use to select name of the keyword component in the keyword structure. -l Compare key lengths before trying a string comparison. This helps cut down on the number of string comparisons made during the lookup. -L Generates code in the language specified by the option's argument. Languages handled are currently C++ and C. The default is C. -n Do not include the length of the keyword when computing the hash function -N Allow user to specify name of generated lookup function. Default name is `in_word_set.' -o Reorders input keys by frequency of occurrence of the key sets. This should decrease the search time dramatically. -p Changes the return value of the generated function ``in_word_set'' from its default boolean value (i.e., 0 or 1), to type ``pointer to wordlist array'' This is most useful when the -t option, allowing user-defined structs, is used. -r Utilizes randomness to initialize the associated values table. -s Affects the size of the generated hash table. The numeric argument for this option indicates ``how many times larger or smaller'' the associated value range should be, in relationship to the number of keys, e.g. a value of 3 means ``allow the maximum associated value to be about 3 times larger than the number of input keys.'' Conversely, a value of -3 means ``make the maximum associated value about 3 times smaller than the number of input keys. A larger table should decrease the time required for an unsuccessful search, at the expense of extra table space. Default value is 1. -S Causes the generated C code to use a switch statement scheme, rather than an array lookup table. This can lead to a reduction in both time and space requirements for some keyfiles. The argument to this option determines how many switch statements are generated. A value of 1 generates 1 switch containing all the elements, a value of 2 generates 2 tables with 1/2 the elements in each table, etc. This is useful since many C compilers cannot correctly generate code for large switch statements. -t Allows the user to include a structured type declaration for generated code. Any text before %% is consider part of the type declaration. Key words and additional fields may follow this, one group of fields per line. -T Prevents the transfer of the type declaration to the output file. Use this option if the type is already defined elsewhere. -v Prints out the current version number Usage: ../gperf [-acCdDef[num]gGhHijkKlLnNoprsStTv]. (type ../gperf -h for help) ude a structured type declaration for generated code. Any text before %% is conslibg++/gperf/tests/expected.out.7 644 473 0 1246 4677677715 12127 in word set if in word set do NOT in word set int in word set for in word set case NOT in word set char NOT in word set auto in word set goto in word set else NOT in word set long NOT in word set void NOT in word set enum NOT in word set float NOT in word set short NOT in word set union NOT in word set break in word set while NOT in word set const NOT in word set double NOT in word set static NOT in word set extern NOT in word set struct in word set return NOT in word set sizeof NOT in word set switch NOT in word set signed NOT in word set typedef NOT in word set default NOT in word set unsigned NOT in word set continue NOT in word set register NOT in word set volatile word set long NOT in word set void NOT in word set enum NOT in word set float NOT in word set short NOT in word set union NOT in word set break in word set while NOT in word set const NOT in word set double NOT in word set static NOT in word set extern NOT in word set struct in word set return NOT in word set sizeof NOT in word set switch NOT ilibg++/gperf/tests/output.pascal 600 473 0 1154 4677677715 12143 in word set with in word set array in word set and in word set function in word set case in word set var in word set const in word set until in word set then in word set set in word set record in word set program in word set procedure in word set or in word set packed in word set not in word set nil in word set label in word set in in word set repeat in word set of in word set goto in word set forward in word set for in word set while in word set file in word set else in word set downto in word set do in word set div in word set to in word set type in word set end in word set mod in word set begin in word set if word set const in word set until in word set then in word set set in word set record in word set program in word set procedure in word set or in word set packed in word set not in word set nil in word set label in word set in in word set repeat in word set of in word set goto in word set forward in word set for in word set while in word set file in word set else in word set downto in word set do in wolibg++/gperf/tests/expected.pasca 600 473 0 1154 4677677715 12230 in word set with in word set array in word set and in word set function in word set case in word set var in word set const in word set until in word set then in word set set in word set record in word set program in word set procedure in word set or in word set packed in word set not in word set nil in word set label in word set in in word set repeat in word set of in word set goto in word set forward in word set for in word set while in word set file in word set else in word set downto in word set do in word set div in word set to in word set type in word set end in word set mod in word set begin in word set if word set const in word set until in word set then in word set set in word set record in word set program in word set procedure in word set or in word set packed in word set not in word set nil in word set label in word set in in word set repeat in word set of in word set goto in word set forward in word set for in word set while in word set file in word set else in word set downto in word set do in wolibg++/gperf/gperf.1 644 473 0 1322 4677677715 7446 .TH GPERF 1 "December 16, 1988 .UC 4 .SH NAME gperf \- generate a perfect hash function from a key set .SH SYNOPSIS .B gperf [ .B \-adghijklnoprsStv ] [ .I keyfile ] .SH DESCRIPTION \fIgperf\fP reads a set of ``keys'' from \fIkeyfile\fP (or, by default, from the standard input) and attempts to find a non-minimal perfect hashing function that recognizes a member of the key set in constant, i.e., O(1), time. If such a function is found the program generates a pair of \fIC\fP source code routines that perform the hashing and table lookup. All generated code is directed to the standard output. Please refer to the \fIgperf.texinfo\fP file for more information. This file is distributed with \fIgperf\fP release. of ``keys'' from \fIkeyfile\fP (or, by default, from the standard input) and attempts to find a non-minimal perfect hashing function that recognizes a member of the key set in constant, i.e., O(1), time. If such a function is found the program generates a pair of \fIC\fP source code routines that perlibg++/gperf/Makefile 644 473 0 2563 4677677715 7731 # Copyright (C) 1989 Free Software Foundation, Inc. # written by Douglas C. Schmidt (schmidt@ics.uci.edu) # # This file is part of GNU GPERF. # # GNU GPERF 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 1, or (at your option) # any later version. # # GNU GPERF 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 GNU GPERF; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. GPERF = ../gperf all: src-dir tests-dir src-dir: -(cd src; $(MAKE); rm -f ../gperf; mv ./gperf ../gperf) tests-dir: gperf -(cd tests; $(MAKE) GPERF=$(GPERF)) distrib: (cd ..; rm -f gperf.tar.Z; tar cvf gperf.tar gperf; compress gperf.tar; uuencode gperf.tar.Z < gperf.tar.Z > GSHAR) shar: (cd ..; makekit -ngperf ./gperf ./gperf/* ./gperf/src/* ./gperf/tests/*; ) clean: (cd src; $(MAKE) clean) (cd tests; $(MAKE) clean) -rm -f *~ realclean: clean -rm -f gperf.info* gperf.?? gperf.??s gperf.log gperf.toc \ gperf.*aux *inset.c *out gperf d src; $(MAKE); rm -f ../gperf; mv ./gperf ../gperf) tests-dir: gperf -(cd tests; $(MAKE) GPERF=$(GPERF)) distrib: (cd ..; rm -f gperf.tlibg++/g++-include/ACG.h 644 473 0 4237 4677677716 7727 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _ACG_h #define _ACG_h 1 #include #include #pragma once // // Additive number generator. This method is presented in Volume II // of The Art of Computer Programming by Knuth. I've coded the algorithm // and have added the extensions by Andres Nowatzyk of CMU to randomize // the result of algorithm M a bit by using an LCG & a spatial // permutation table. // // The version presented uses the same constants for the LCG that Andres // uses (chosen by trial & error). The spatial permutation table is // the same size (it's based on word size). This is for 32-bit words. // // The ``auxillary table'' used by the LCG table varies in size, and // is chosen to be the the smallest power of two which is larger than // twice the size of the state table. // class ACG : public RNG { unsigned long initialSeed; // used to reset generator int initialTableEntry; unsigned long *state; unsigned long *auxState; short stateSize; short auxSize; unsigned long lcgRecurr; short j; short k; protected: public: ACG(unsigned long seed = 0, int size = 55); virtual ~ACG(); // // Return a long-words word of random bits // virtual unsigned long asLong(); virtual void reset(); }; #endif ze of the state table. // class ACG : public RNG { unsigned long initialSeed; // used to reset generator int initialTableEntry; unsigned long *state; unsigned long *auxState; short stateSize; short auxSize; unsigned long lcgRecurr; short j; short k; protected: public: ACG(unsigned long seed = 0, int size = libg++/g++-include/Binomial.h 644 473 0 3100 4677677716 11053 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Binomial_h #pragma once #define _Binomial_h 1 #include class Binomial: public Random { protected: int pN; double pU; public: Binomial(int n, double u, RNG *gen); int n(); int n(int xn); double u(); double u(int xu); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Binomial::Binomial(int n, double u, RNG *gen) : (gen){ pN = n; pU = u; } inline int Binomial::n() { return pN; } inline int Binomial::n(int xn) { int tmp = pN; pN = xn; return tmp; } inline double Binomial::u() { return pU; } inline double Binomial::u(int xu) { double tmp = pU; pU = xu; return tmp; } //#endif #endif ublic: Binomial(int n, double u, RNG *gen); int n(); int n(int xn); double u(); double u(int xu); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Binomial::Binomial(int n, double u, RNG *gen) : (gen){ pN = n; pU = u; } inline int Binomial::n() { return pN; } inline int Binomial::n(int xn) { int tmp = pN; pN = xn; return tmp; } inline double Binomial::u() { return pU; } inline double Binomial::u(intlibg++/g++-include/BitSet.h 644 473 0 20376 4677677716 10551 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _BitSet_h #pragma once #define _BitSet_h 1 #include #include #define BITSETBITS BITS(short) struct BitSetRep { unsigned short len; // number of shorts in s unsigned short sz; // allocated slots unsigned short virt; // virtual 0 or 1 unsigned short s[1]; // bits start here }; extern BitSetRep* BitSetalloc(BitSetRep*, const unsigned short*, int, int, int); extern BitSetRep* BitSetcopy(BitSetRep*, const BitSetRep*); extern BitSetRep* BitSetresize(BitSetRep*, int); extern BitSetRep* BitSetop(const BitSetRep*, const BitSetRep*, BitSetRep*, char); extern BitSetRep* BitSetcmpl(const BitSetRep*, BitSetRep*); extern BitSetRep _nilBitSetRep; class BitSet; class BitSetBit { protected: BitSet* src; unsigned long pos; public: BitSetBit(BitSet* v, int p); BitSetBit(const BitSetBit& b); ~BitSetBit(); operator int(); int operator = (int b); int operator == (int b); int operator != (int b); }; class BitSet { protected: BitSetRep* rep; public: // constructors BitSet(); BitSet(const BitSet&); ~BitSet(); void operator = (const BitSet& y); // equality & subset tests friend int operator == (const BitSet& x, const BitSet& y); friend int operator != (const BitSet& x, const BitSet& y); friend int operator < (const BitSet& x, const BitSet& y); friend int operator <= (const BitSet& x, const BitSet& y); friend int operator > (const BitSet& x, const BitSet& y); friend int operator >= (const BitSet& x, const BitSet& y); // operations on self void operator |= (const BitSet& y); void operator &= (const BitSet& y); void operator -= (const BitSet& y); void operator ^= (const BitSet& y); void complement(); // individual bit manipulation void set(int pos); void set(int from, int to); void set(); // set all void clear(int pos); void clear(int from, int to); void clear(); // clear all void invert(int pos); void invert(int from, int to); int test(int pos) const; int test(int from, int to) const; BitSetBit operator [] (int i); // iterators int first(int b = 1) const; int last(int b = 1) const; int next(int pos, int b = 1) const; int previous(int pos, int b = 1) const; // status int empty() const; int virtual_bit() const; int count(int b = 1) const; // convertors & IO friend BitSet atoBitSet(const char* s, char f='0', char t='1', char star='*'); friend const char* BitSettoa(const BitSet& x, char f='0', char t='1', char star='*'); friend BitSet shorttoBitSet(unsigned short w); friend BitSet longtoBitSet(unsigned long w); friend ostream& operator << (ostream& s, const BitSet& x); // procedural versions of operators friend void and(const BitSet& x, const BitSet& y, BitSet& r); friend void or(const BitSet& x, const BitSet& y, BitSet& r); friend void xor(const BitSet& x, const BitSet& y, BitSet& r); friend void diff(const BitSet& x, const BitSet& y, BitSet& r); friend void complement(const BitSet& x, BitSet& r); // misc volatile void error(const char* msg) const; int OK() const; }; typedef BitSet BitSetTmp; /* operators declared inline below BitSet operator | (const BitSet& x, const BitSet& y); BitSet operator & (const BitSet& x, const BitSet& y); BitSet operator - (const BitSet& x, const BitSet& y); BitSet operator ^ (const BitSet& x, const BitSet& y); BitSet operator ~ (const BitSet& x); */ //#ifdef __OPTIMIZE__ inline int BitSet_index(int l) { return (unsigned)(l) / BITSETBITS; } inline int BitSet_pos(int l) { return l & (BITSETBITS - 1); } inline BitSet::BitSet() : rep(&_nilBitSetRep) {} inline BitSet::BitSet(const BitSet& x) :rep(BitSetcopy(0, x.rep)) {} inline BitSet::~BitSet() { if (rep != &_nilBitSetRep) delete rep; } inline void BitSet::operator = (const BitSet& y) { rep = BitSetcopy(rep, y.rep); } inline int operator != (const BitSet& x, const BitSet& y) { return !(x == y); } inline int operator > (const BitSet& x, const BitSet& y) { return y < x; } inline int operator >= (const BitSet& x, const BitSet& y) { return y <= x; } inline void and(const BitSet& x, const BitSet& y, BitSet& r) { r.rep = BitSetop(x.rep, y.rep, r.rep, '&'); } inline void or(const BitSet& x, const BitSet& y, BitSet& r) { r.rep = BitSetop(x.rep, y.rep, r.rep, '|'); } inline void xor(const BitSet& x, const BitSet& y, BitSet& r) { r.rep = BitSetop(x.rep, y.rep, r.rep, '^'); } inline void diff(const BitSet& x, const BitSet& y, BitSet& r) { r.rep = BitSetop(x.rep, y.rep, r.rep, '-'); } inline void complement(const BitSet& x, BitSet& r) { r.rep = BitSetcmpl(x.rep, r.rep); } inline BitSet operator & (const BitSet& x, const BitSet& y) return r { and(x, y, r); } inline BitSet operator | (const BitSet& x, const BitSet& y) return r { or(x, y, r); } inline BitSet operator ^ (const BitSet& x, const BitSet& y) return r { xor(x, y, r); } inline BitSet operator - (const BitSet& x, const BitSet& y) return r { diff(x, y, r); } inline BitSet operator ~ (const BitSet& x) return r { ::complement(x, r); } inline void BitSet::operator &= (const BitSet& y) { and(*this, y, *this); } inline void BitSet::operator |= (const BitSet& y) { or(*this, y, *this); } inline void BitSet::operator ^= (const BitSet& y) { xor(*this, y, *this); } inline void BitSet::operator -= (const BitSet& y) { diff(*this, y, *this); } inline void BitSet::complement() { ::complement(*this, *this); } inline int BitSet::virtual_bit() const { return rep->virt; } inline int BitSet::first(int b) const { return next(-1, b); } inline int BitSet::test(int p) const { if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); return (index >= rep->len)? rep->virt : ((rep->s[index] & (1 << BitSet_pos(p))) != 0); } inline void BitSet::clear() { if (rep->len > 0) bzero(rep->s, rep->sz * sizeof(short)); rep->len = rep->virt = 0; } inline void BitSet::set() { rep = BitSetalloc(rep, 0, 0, 1, 0); } inline BitSetBit::BitSetBit(const BitSetBit& b) :src(b.src), pos(b.pos) {} inline BitSetBit::BitSetBit(BitSet* v, int p) { src = v; pos = p; } inline BitSetBit::~BitSetBit() {} inline BitSetBit::operator int() { return src->test(pos); } inline int BitSetBit::operator = (int b) { if (b) src->set(pos); else src->clear(pos); return b; } inline int BitSetBit::operator == (int b) { return src->test(pos) == b; } inline int BitSetBit::operator != (int b) { return src->test(pos) != b; } inline BitSetBit BitSet::operator [] (int i) { if (i < 0) error("illegal bit index"); return BitSetBit(this, i); } //#endif #endif c = v; pos = p; } inline BitSetBit::~BitSetBit() {} inline BitSetBit::operator int() { return src->test(pos); } inline int BitSetBit::operator = (int b) { if (b) src->set(pos); else src->clear(pos); return b; } inline int BitSetBit::operator == (intlibg++/g++-include/BitString.h 644 473 0 43112 4677677717 11256 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _BitString_h #pragma once #define _BitString_h 1 #include #include #define BITSTRBITS BITS(short) struct BitStrRep { unsigned int len; // length in bits unsigned short sz; // allocated slots unsigned short s[1]; // bits start here }; extern BitStrRep* BStr_alloc(BitStrRep*, const unsigned short*, int, int,int); extern BitStrRep* BStr_resize(BitStrRep*, int); extern BitStrRep* BStr_copy(BitStrRep*, const BitStrRep*); extern BitStrRep* cmpl(const BitStrRep*, BitStrRep*); extern BitStrRep* and(const BitStrRep*, const BitStrRep*, BitStrRep*); extern BitStrRep* or(const BitStrRep*, const BitStrRep*, BitStrRep*); extern BitStrRep* xor(const BitStrRep*, const BitStrRep*, BitStrRep*); extern BitStrRep* diff(const BitStrRep*, const BitStrRep*, BitStrRep*); extern BitStrRep* cat(const BitStrRep*, const BitStrRep*, BitStrRep*); extern BitStrRep* cat(const BitStrRep*, unsigned int, BitStrRep*); extern BitStrRep* lshift(const BitStrRep*, int, BitStrRep*); class BitString; class BitPattern; class BitStrBit { protected: BitString& src; unsigned int pos; public: BitStrBit(BitString& v, int p); BitStrBit(const BitStrBit& b); ~BitStrBit(); operator unsigned int() const; int operator = (unsigned int b); int operator == (unsigned int b) const ; int operator != (unsigned int b) const ; }; class BitSubString { friend class BitString; friend class BitPattern; protected: BitString& S; int pos; int len; BitSubString(BitString& x, int p, int l); BitSubString(const BitSubString& x); public: ~BitSubString(); void operator = (const BitString&); void operator = (const BitSubString&); int length() const; int empty() const; int OK() const; }; class BitString { friend class BitSubString; friend class BitPattern; protected: BitStrRep* rep; int search(int, int, const unsigned short*, int, int) const; int match(int, int, int, const unsigned short*,int,int) const; BitSubString _substr(int first, int l); public: // constructors BitString(); BitString(const BitString&); BitString(const BitSubString& y); ~BitString(); void operator = (unsigned int bit); void operator = (const BitString& y); void operator = (const BitSubString& y); // equality & subset tests friend int operator == (const BitString&, const BitString&); friend int operator != (const BitString&, const BitString&); friend int operator < (const BitString&, const BitString&); friend int operator <= (const BitString&, const BitString&); friend int operator > (const BitString&, const BitString&); friend int operator >= (const BitString&, const BitString&); // procedural versions of operators friend void and(const BitString&, const BitString&, BitString&); friend void or(const BitString&, const BitString&, BitString&); friend void xor(const BitString&, const BitString&, BitString&); friend void diff(const BitString&, const BitString&, BitString&); friend void cat(const BitString&, const BitString&, BitString&); friend void cat(const BitString&, unsigned int, BitString&); friend void lshift(const BitString&, int, BitString&); friend void rshift(const BitString&, int, BitString&); friend void complement(const BitString&, BitString&); friend int lcompare(const BitString&, const BitString&); // assignment-based operators // (constuctive versions decalred inline below void operator |= (const BitString&); void operator &= (const BitString&); void operator -= (const BitString&); void operator ^= (const BitString&); void operator += (const BitString&); void operator += (unsigned int b); void operator <<=(int s); void operator >>=(int s); void complement(); // individual bit manipulation void set(int pos); void set(int from, int to); void set(); void clear(int pos); void clear(int from, int to); void clear(); void invert(int pos); void invert(int from, int to); int test(int pos) const; int test(int from, int to) const; void assign(int p, unsigned int bit); // indexing BitStrBit operator [] (int pos); // iterators int first(unsigned int bit = 1) const; int last(unsigned int b = 1) const; int next(int pos, unsigned int b = 1) const; int previous(int pos, unsigned int b = 1) const; // searching & matching int index(unsigned int bit, int startpos = 0) const ; int index(const BitString&, int startpos = 0) const; int index(const BitSubString&, int startpos = 0) const; int index(const BitPattern&, int startpos = 0) const; int contains(const BitString&) const; int contains(const BitSubString&) const; int contains(const BitPattern&) const; int contains(const BitString&, int pos) const; int contains(const BitSubString&, int pos) const; int contains(const BitPattern&, int pos) const; int matches(const BitString&, int pos = 0) const; int matches(const BitSubString&, int pos = 0) const; int matches(const BitPattern&, int pos = 0) const; // BitSubString extraction BitSubString at(int pos, int len); BitSubString at(const BitString&, int startpos = 0); BitSubString at(const BitSubString&, int startpos = 0); BitSubString at(const BitPattern&, int startpos = 0); BitSubString before(int pos); BitSubString before(const BitString&, int startpos = 0); BitSubString before(const BitSubString&, int startpos = 0); BitSubString before(const BitPattern&, int startpos = 0); BitSubString after(int pos); BitSubString after(const BitString&, int startpos = 0); BitSubString after(const BitSubString&, int startpos = 0); BitSubString after(const BitPattern&, int startpos = 0); // other friends & utilities friend BitString common_prefix(const BitString&, const BitString&, int pos = 0); friend BitString common_suffix(const BitString&, const BitString&, int pos = -1); friend BitString reverse(const BitString&); void right_trim(unsigned int bit); void left_trim(unsigned int bit); // status int empty() const ; int count(unsigned int bit = 1) const; int length() const; // convertors & IO friend BitString atoBitString(const char* s, char f='0', char t='1'); friend const char* BitStringtoa(const BitString&, char f='0', char t='1'); friend BitString shorttoBitString(unsigned short); friend BitString longtoBitString(unsigned long); friend ostream& operator << (ostream& s, const BitString&); // misc volatile void error(const char* msg) const; // indirect friends friend const char* BitPatterntoa(const BitPattern& p, char f='0',char t='1',char x='X'); friend BitPattern atoBitPattern(const char* s, char f='0',char t='1',char x='X'); int OK() const; }; class BitPattern { public: BitString pattern; BitString mask; BitPattern(); BitPattern(const BitPattern&); BitPattern(const BitString& p, const BitString& m); ~BitPattern(); friend const char* BitPatterntoa(const BitPattern&, char f, char t, char x); friend BitPattern atoBitPattern(const char* s, char f,char t, char x); friend ostream& operator << (ostream& s, const BitPattern&); int search(const unsigned short*, int, int) const; int match(const unsigned short* xs, int, int, int) const; int OK() const; }; //#ifdef __OPTIMIZE__ // primitive bit extraction inline static int BitStr_index(int l) { return (unsigned)(l) / BITSTRBITS; } inline static int BitStr_pos(int l) { return l & (BITSTRBITS - 1); } extern BitStrRep _nilBitStrRep; extern BitString _nil_BitString; // constructors & assignment inline BitString::BitString() :rep(&_nilBitStrRep) {} inline BitString::BitString(const BitString& x) :rep(BStr_copy(0, x.rep)) {} inline BitString::BitString(const BitSubString& y) :rep (BStr_alloc(0, y.S.rep->s, y.pos, y.pos+y.len, y.len)) {} inline BitString::~BitString() { if (rep != &_nilBitStrRep) delete rep; } inline BitString shorttoBitString(unsigned short w) return r { r.rep = BStr_alloc(0, &w, 0, BITSTRBITS, BITSTRBITS); } inline void BitString::operator = (const BitString& y) { rep = BStr_copy(rep, y.rep); } inline void BitString::operator = (unsigned int b) { unsigned short bit = b; rep = BStr_alloc(rep, &bit, 0, 1, 1); } inline void BitString::operator=(const BitSubString& y) { rep = BStr_alloc(rep, y.S.rep->s, y.pos, y.pos+y.len, y.len); } inline BitSubString::BitSubString(const BitSubString& x) :S(x.S), pos(x.pos), len(x.len) {} inline BitSubString::BitSubString(BitString& x, int p, int l) : S(x), pos(p), len(l) {} inline BitSubString::~BitSubString() {} inline BitPattern::BitPattern(const BitString& p, const BitString& m) :pattern(p), mask(m) {} inline BitPattern::BitPattern(const BitPattern& b) :pattern(b.pattern), mask(b.mask) {} inline BitPattern::BitPattern() {} inline BitPattern::~BitPattern() {} inline BitString longtoBitString(unsigned long w) return r { unsigned short u[2]; u[0] = w & ((unsigned short)(~(0))); u[1] = w >> BITSTRBITS; r.rep = BStr_alloc(0, &u[0], 0, 2*BITSTRBITS, 2*BITSTRBITS); } // procedural versions of operators inline void and(const BitString& x, const BitString& y, BitString& r) { r.rep = and(x.rep, y.rep, r.rep); } inline void or(const BitString& x, const BitString& y, BitString& r) { r.rep = or(x.rep, y.rep, r.rep); } inline void xor(const BitString& x, const BitString& y, BitString& r) { r.rep = xor(x.rep, y.rep, r.rep); } inline void diff(const BitString& x, const BitString& y, BitString& r) { r.rep = diff(x.rep, y.rep, r.rep); } inline void cat(const BitString& x, const BitString& y, BitString& r) { r.rep = cat(x.rep, y.rep, r.rep); } inline void cat(const BitString& x, unsigned int y, BitString& r) { r.rep = cat(x.rep, y, r.rep); } inline void rshift(const BitString& x, int y, BitString& r) { r.rep = lshift(x.rep, -y, r.rep); } inline void lshift(const BitString& x, int y, BitString& r) { r.rep = lshift(x.rep, y, r.rep); } inline void complement(const BitString& x, BitString& r) { r.rep = cmpl(x.rep, r.rep); } // operators inline BitString operator & (const BitString& x, const BitString& y) return r { and(x, y, r); } inline void BitString::operator &= (const BitString& y) { and(*this, y, *this); } inline BitString operator | (const BitString& x, const BitString& y) return r { or(x, y, r); } inline void BitString::operator |= (const BitString& y) { or(*this, y, *this); } inline BitString operator ^ (const BitString& x, const BitString& y) return r { xor(x, y, r); } inline void BitString::operator ^= (const BitString& y) { xor(*this, y, *this); } inline BitString operator << (const BitString& x, int y) return r { lshift(x, y, r); } inline void BitString::operator <<= (int y) { lshift(*this, y, *this); } inline BitString operator >> (const BitString& x, int y) return r { rshift(x, y, r); } inline void BitString::operator >>= (int y) { rshift(*this, y, *this); } inline BitString operator - (const BitString& x, const BitString& y) return r { diff(x, y, r); } inline void BitString::operator -= (const BitString& y) { diff(*this, y, *this); } inline BitString operator + (const BitString& x, const BitString& y) return r { cat(x, y, r); } inline void BitString::operator += (const BitString& y) { cat(*this, y, *this); } inline BitString operator + (const BitString& x, unsigned int y) return r { cat(x, y, r); } inline void BitString::operator += (unsigned int y) { cat(*this, y, *this); } inline BitString operator ~ (const BitString& x) return r { complement(x, r); } inline void BitString::complement() { ::complement(*this, *this); } // status, matching inline int BitString::length() const { return rep->len; } inline int BitString::empty() const { return rep->len == 0; } inline int BitString::index(const BitString& y, int startpos) const { return search(startpos, rep->len, y.rep->s, 0, y.rep->len); } inline int BitString::index(const BitSubString& y, int startpos) const { return search(startpos, rep->len, y.S.rep->s, y.pos, y.pos+y.len); } inline int BitString::contains(const BitString& y) const { return search(0, rep->len, y.rep->s, 0, y.rep->len) >= 0; } inline int BitString::contains(const BitSubString& y) const { return search(0, rep->len, y.S.rep->s, y.pos, y.pos+y.len) >= 0; } inline int BitString::contains(const BitString& y, int p) const { return match(p, rep->len, 0, y.rep->s, 0, y.rep->len); } inline int BitString::matches(const BitString& y, int p) const { return match(p, rep->len, 1, y.rep->s, 0, y.rep->len); } inline int BitString::contains(const BitSubString& y, int p) const { return match(p, rep->len, 0, y.S.rep->s, y.pos, y.pos+y.len); } inline int BitString::matches(const BitSubString& y, int p) const { return match(p, rep->len, 1, y.S.rep->s, y.pos, y.pos+y.len); } inline int BitString::contains(const BitPattern& r) const { return r.search(rep->s, 0, rep->len) >= 0; } inline int BitString::contains(const BitPattern& r, int p) const { return r.match(rep->s, p, rep->len, 0); } inline int BitString::matches(const BitPattern& r, int p) const { return r.match(rep->s, p, rep->len, 1); } inline int BitString::index(const BitPattern& r, int startpos) const { return r.search(rep->s, startpos, rep->len); } inline int BitSubString::length() const { return len; } inline int BitSubString::empty() const { return len == 0; } inline int operator != (const BitString& x, const BitString& y) { return !(x == y); } inline int operator>(const BitString& x, const BitString& y) { return y < x; } inline int operator>=(const BitString& x, const BitString& y) { return y <= x; } inline int BitString::first(unsigned int b) const { return next(-1, b); } inline int BitString::last(unsigned int b) const { return previous(rep->len, b); } inline int BitString::index(unsigned int bit, int startpos) const { if (startpos >= 0) return next(startpos - 1, bit); else return previous(rep->len + startpos + 1, bit); } inline void BitString::right_trim(unsigned int b) { int nb = (b == 0)? 1 : 0; rep = BStr_resize(rep, previous(rep->len, nb) + 1); } inline void BitString::left_trim(unsigned int b) { int nb = (b == 0)? 1 : 0; int p = next(-1, nb); rep = BStr_alloc(rep, rep->s, p, rep->len, rep->len - p); } inline int BitString::test(int i) const { return ((unsigned)(i) >= rep->len)? 0 : ((rep->s[BitStr_index(i)] & (1 << (BitStr_pos(i)))) != 0); } // subscripting inline BitStrBit::BitStrBit(const BitStrBit& b) :src(b.src), pos(b.pos) {} inline BitStrBit::BitStrBit(BitString& v, int p) :src(v), pos(p) {} inline BitStrBit::~BitStrBit() {} inline BitStrBit::operator unsigned int() const { return src.test(pos); } inline int BitStrBit::operator = (unsigned int b) { src.assign(pos, b); return b; } inline int BitStrBit::operator == (unsigned int b) const { return src.test(pos) == b; } inline int BitStrBit::operator != (unsigned int b) const { return src.test(pos) != b; } inline BitStrBit BitString::operator [] (int i) { if ((unsigned)(i) >= rep->len) error("illegal bit index"); return BitStrBit(*this, i); } inline BitSubString BitString::_substr(int first, int l) { if (first < 0 || l <= 0 || (unsigned)(first + l) > rep->len) return BitSubString(_nil_BitString, 0, 0) ; else return BitSubString(*this, first, l); } //#endif #endif st { return src.test(pos) == b; } inline int BitStrBit::operator != (unsigned int b) const { return src.test(pos) != b; } inline BitStrBit BitString::operator [] (int i) { if ((unsigned)(i) >= rep->len) error("illegal bit index"); return BitStrBit(*this, i); } inline BitSubString BitString::_substr(int first, int l) { if (first < 0 || l <= 0 || (unsigned)(first + l) > rep->len) return BitSubString(_nil_BitString, 0, 0libg++/g++-include/Complex.h 644 473 0 14334 4677677717 10764 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Complex_h #pragma once #define _Complex_h 1 #include #include class Complex { protected: double re; double im; public: inline double /* const */ real() const; inline double /* const */ imag() const; inline Complex(); inline Complex(const Complex& y); inline Complex(double r, double i=0); inline ~Complex(); inline Complex& operator = (const Complex& y); inline Complex& operator += (const Complex& y); inline Complex& operator += (double y); inline Complex& operator -= (const Complex& y); inline Complex& operator -= (double y); inline Complex& operator *= (const Complex& y); inline Complex& operator *= (double y); Complex& operator /= (const Complex& y); Complex& operator /= (double y); void error(const char* msg) const; }; // inline members inline double /* const */ Complex::real() const { return re; } inline double /* const */ Complex::imag() const { return im; } inline Complex::Complex() {} inline Complex::Complex(const Complex& y) :re(y.real()), im(y.imag()) {} inline Complex::Complex(double r, double i) :re(r), im(i) {} inline Complex::~Complex() {} inline Complex& Complex::operator = (const Complex& y) { re = y.real(); im = y.imag(); return *this; } inline Complex& Complex::operator += (const Complex& y) { re += y.real(); im += y.imag(); return *this; } inline Complex& Complex::operator += (double y) { re += y; return *this; } inline Complex& Complex::operator -= (const Complex& y) { re -= y.real(); im -= y.imag(); return *this; } inline Complex& Complex::operator -= (double y) { re -= y; return *this; } inline Complex& Complex::operator *= (const Complex& y) { double r = re * y.real() - im * y.imag(); im = re * y.imag() + im * y.real(); re = r; return *this; } inline Complex& Complex::operator *= (double y) { re *= y; im *= y; return *this; } // error handlers extern void default_Complex_error_handler(const char*); extern one_arg_error_handler_t Complex_error_handler; extern one_arg_error_handler_t set_Complex_error_handler(one_arg_error_handler_t f); // non-inline functions Complex /* const */ operator / (const Complex& x, const Complex& y); Complex /* const */ operator / (const Complex& x, double y); Complex /* const */ operator / (double x, const Complex& y); Complex /* const */ cos(const Complex& x); Complex /* const */ sin(const Complex& x); Complex /* const */ cosh(const Complex& x); Complex /* const */ sinh(const Complex& x); Complex /* const */ exp(const Complex& x); Complex /* const */ log(const Complex& x); Complex /* const */ pow(const Complex& x, long p); Complex /* const */ pow(const Complex& x, const Complex& p); Complex /* const */ sqrt(const Complex& x); istream& operator >> (istream& s, Complex& x); ostream& operator << (ostream& s, const Complex& x); // inline functions inline int /* const */ operator == (const Complex& x, const Complex& y) { return x.real() == y.real() && x.imag() == y.imag(); } inline int /* const */ operator == (const Complex& x, double y) { return x.imag() == 0.0 && x.real() == y; } inline int /* const */ operator != (const Complex& x, const Complex& y) { return x.real() != y.real() || x.imag() != y.imag(); } inline int /* const */ operator != (const Complex& x, double y) { return x.imag() != 0.0 || x.real() != y; } inline Complex /* const */ operator - (const Complex& x) { return Complex(-x.real(), -x.imag()); } inline Complex /* const */ conj(const Complex& x) { return Complex(x.real(), -x.imag()); } inline Complex /* const */ operator + (const Complex& x, const Complex& y) { return Complex(x.real() + y.real(), x.imag() + y.imag()); } inline Complex /* const */ operator + (const Complex& x, double y) { return Complex(x.real() + y, x.imag()); } inline Complex /* const */ operator + (double x, const Complex& y) { return Complex(x + y.real(), y.imag()); } inline Complex /* const */ operator - (const Complex& x, const Complex& y) { return Complex(x.real() - y.real(), x.imag() - y.imag()); } inline Complex /* const */ operator - (const Complex& x, double y) { return Complex(x.real() - y, x.imag()); } inline Complex /* const */ operator - (double x, const Complex& y) { return Complex(x - y.real(), -y.imag()); } inline Complex /* const */ operator * (const Complex& x, const Complex& y) { return Complex(x.real() * y.real() - x.imag() * y.imag(), x.real() * y.imag() + x.imag() * y.real()); } inline Complex /* const */ operator * (const Complex& x, double y) { return Complex(x.real() * y, x.imag() * y); } inline Complex /* const */ operator * (double x, const Complex& y) { return Complex(x * y.real(), x * y.imag()); } inline double /* const */ real(const Complex& x) { return x.real(); } inline double /* const */ imag(const Complex& x) { return x.imag(); } inline double /* const */ abs(const Complex& x) { return hypot(x.real(), x.imag()); } inline double /* const */ norm(const Complex& x) { return (x.real() * x.real() + x.imag() * x.imag()); } inline double /* const */ arg(const Complex& x) { return atan2(x.imag(), x.real()); } inline Complex /* const */ polar(double r, double t = 0.0) { return Complex(r * cos(t), r * sin(t)); } #endif nst Complex& x) { return x.real(); } inline double /* const */ imag(const Complex& x) { return x.imag(); } inline double /* const */ abs(const Complex& x) { return hypot(x.real(), x.imag()); } inline double /* const */ norm(const Complex& x) { return (x.real() * x.real() + x.imag(libg++/g++-include/DiscreteUnifor 644 473 0 3572 4677677717 12036 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _DiscreteUniform_h #pragma once #define _DiscreteUniform_h 1 #include // // The interval [lo..hi) // class DiscreteUniform: public Random { long pLow; long pHigh; double delta; public: DiscreteUniform(long low, long high, RNG *gen); long low(); long low(long x); long high(); long high(long x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline DiscreteUniform::DiscreteUniform(long low, long high, RNG *gen) : (gen) { pLow = (low < high) ? low : high; pHigh = (low < high) ? high : low; delta = (pHigh - pLow) + 1; } inline long DiscreteUniform::low() { return pLow; } inline long DiscreteUniform::low(long x) { long tmp = pLow; pLow = x; delta = (pHigh - pLow) + 1; return tmp; } inline long DiscreteUniform::high() { return pHigh; } inline long DiscreteUniform::high(long x) { long tmp = pHigh; pHigh = x; delta = (pHigh - pLow) + 1; return tmp; } //#endif #endif long high, RNG *gen) : (gen) { pLow = (low < high) ? low : high; pHigh = (low < high) ? high : low; delta = (pHigh - pLow)libg++/g++-include/Erlang.h 644 473 0 3631 4677677717 10543 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Erlang_h #pragma once #define _Erlang_h 1 #include class Erlang: public Random { protected: double pMean; double pVariance; int k; double a; void setState(); public: Erlang(double mean, double variance, RNG *gen); double mean(); double mean(double x); double variance(); double variance(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline void Erlang::setState() { k = int( (pMean * pMean ) / pVariance + 0.5 ); k = (k > 0) ? k : 1; a = k / pMean; } inline Erlang::Erlang(double mean, double variance, RNG *gen) : (gen) { pMean = mean; pVariance = variance; setState(); } inline double Erlang::mean() { return pMean; } inline double Erlang::mean(double x) { double tmp = pMean; pMean = x; setState(); return tmp; }; inline double Erlang::variance() { return pVariance; } inline double Erlang::variance(double x) { double tmp = pVariance; pVariance = x; setState(); return tmp; } //#endif #endif nce + 0.5 ); k = (k > 0) ? k : 1; a = k / pMean; } inline Erlang::Erlang(double mean, double varialibg++/g++-include/File.h 644 473 0 17326 4677677717 10240 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _File_h #pragma once #define _File_h 1 #include #include #include enum io_mode // known unix file IO modes { io_readonly = 0, io_writeonly = 1, io_readwrite = 2, io_appendonly = 3, io_append = 4, // append, plus allow reads }; enum access_mode // ways to open a file { a_createonly = 0, // create, fail if file exists a_create = 1, // create if doesn't exist, else truncate a_useonly = 2, // use (no truncate) fail if doesn't exist a_use = 3, // use (no truncate), create if doesn't exist }; enum state_value // File states { _good = 0, // all is well _eof = 1, // at eof _fail = 2, // logical or physical IO error _bad = 4 // unopened/corrupted }; class Filebuf; class File { friend class Filebuf; protected: FILE* fp; // _iobuf file pointer char* nm; // file name (dynamically allocated) char rw; // 1 = read; 2 = write; 3 = readwrite // bit 2 (4) means read/write into string state_value state; // _good/_eof/_fail/_bad long stat; // last read/write/... return value void initialize(); void reinitialize(const char*); char *readline (int chunk_number, char terminator); public: File(); File(const char* filename, io_mode m, access_mode a); File(const char* filename, const char* m); File(int filedesc, io_mode m); File(FILE* fileptr); File(int sz, char* buf, io_mode m); ~File(); // binding, rebinding, unbinding to physical files File& open(const char* filename, io_mode m, access_mode a); File& open(const char* filename, const char* m); File& open(int filedesc, io_mode m); File& open(FILE* fileptr); File& close(); File& remove(); // class variable access int filedesc(); const char* name(); void setname(const char* newname); int iocount(); int rdstate(); int eof(); int fail(); int bad(); int good(); // other status queries int readable(); int writable(); int is_open(); operator void*(); // error handling void error(); void clear(state_value f = _good); // poorly named void set(state_value f); // set corresponding but void unset(state_value f); // clear corresponding bit File& failif(int cond); void check_state(); // character IO File& get(char& c); File& put(char c); File& unget(char c); File& putback(char c); // a synonym for unget // char* IO File& put(const char* s); File& get (char* s, int n, char terminator = '\n'); File& getline(char* s, int n, char terminator = '\n'); File& gets (char **s, char terminator = '\n'); // binary IO File& read(void* x, int sz, int n); File& write(void* x, int sz, int n); // formatted IO File& form(const char* ...); File& scan(const char* ...); // buffer IO File& flush(); File& flush(char ch); // call stdio _flsbuf int fill(); // call stdio _filbuf // position control File& seek(long pos, int seek_mode=0); // default seek mode=absolute long tell(); // buffer control File& setbuf(int buffer_kind); // legal vals: _IONBF, _IOFBF, _IOLBF File& setbuf(int size, char* buf); File& raw(); }; // error handlers extern void verbose_File_error_handler(const char*); extern void quiet_File_error_handler(const char*); extern void fatal_File_error_handler(const char*); extern one_arg_error_handler_t File_error_handler; extern one_arg_error_handler_t set_File_error_handler(one_arg_error_handler_t); //#ifdef __OPTIMIZE__ inline int File::filedesc() { return fileno(fp); } inline const char* File::name() { return nm; } inline int File::iocount() { return stat; } inline void File::clear(state_value flag) { state = flag; } inline void File::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void File::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int File::readable() { if (fp != 0) { if (feof(fp)) set(_eof); if (ferror(fp)) set(_bad);} return (state == _good && (rw & 01)); } inline int File::writable() { if (fp != 0 && ferror(fp)) set(_bad); return ((int(state) & (int(_fail)|int(_bad))) == 0 && (rw & 02)); } inline int File::is_open() { return (fp != 0); } inline File& File::raw() { return this->File::setbuf(_IONBF); } inline File& File::failif(int cond) { if (cond) set(_fail); return *this; } inline File& File::get(char& c) { if (readable()) { int ch = getc(fp); c = ch; failif (ch == EOF); } return *this; } inline File& File::put(char c) { return failif (!writable() || putc(c, fp) == EOF); } inline File& File::unget(char c) { return failif(!is_open() || !(rw & 01) || ungetc(c, fp) == EOF); } inline File& File::putback(char c) { return failif (!is_open() || !(rw & 01) || ungetc(c, fp) == EOF); } inline File& File::read(void* x, int sz, int n) { return failif (!readable() || (stat = fread(x, sz, n, fp)) != n); } inline File& File::write(void* x, int sz, int n) { return failif (!writable() || (stat = fwrite(x, sz, n, fp)) != n); } inline File& File::flush() { return failif(!is_open() || fflush(fp) == EOF); } inline File& File::flush(char ch) { return failif(!is_open() || _flsbuf(ch, fp) == EOF); } inline int File::fill() { failif(!is_open() || (stat = _filbuf(fp)) == EOF); return stat; } inline File& File::seek(long pos, int seek_mode) { return failif (!is_open() || fseek(fp, pos, seek_mode) < 0); } inline long File::tell() { failif (!is_open() || ((stat = ftell(fp)) < 0)); return stat; } inline int File::rdstate() { check_state(); return state; // check_state is necessary in rare but } // possible circumstances inline File::operator void*() { check_state(); return (int(state) & (int(_bad)|int(_fail)))? 0 : this ; } inline int File::eof() { check_state(); return state & _eof; } inline int File::fail() { check_state(); return state & _fail; } inline int File::bad() { check_state(); return state & _bad; } inline int File::good() { check_state(); return rdstate() == _good; } //#endif #endif ; // check_state is necessary in rare but } // possible circumstances inline File::operator void*() { check_state(); return (int(state) & (int(_bad)|int(_fail)))? 0 : this ; } inline int File::eof() { check_state(); return state & _eof; } inline int File::libg++/g++-include/Fix.h 644 473 0 22703 4677677720 10074 // // Fix.h : variable length fixed point data type // #ifndef _Fix_h #pragma once #define _Fix_h 1 #include #include #include #include typedef unsigned short uint16; typedef short int16; typedef unsigned long uint32; typedef long int32; #define _Fix_min_length 1 #define _Fix_max_length 65535 #define _Fix_min_value -1.0 #define _Fix_max_value 1.0 extern uint16 Fix_default_length; extern int Fix_default_print_width; struct _Frep // internal Fix representation { uint16 len; // length in bits uint16 siz; // allocated storage int16 ref; // reference count uint16 s[1]; // start of ushort array represention }; typedef struct _Frep* _Fix; extern _Frep _Frep_0; extern _Frep _Frep_m1; extern _Frep _Frep_quotient_bump; class Fix { _Fix rep; Fix(_Fix); void unique(); public: Fix(); Fix(Fix&); Fix(double&); Fix(int); Fix(int, Fix&); Fix(int, double&); Fix(int, _Frep*); ~Fix(); Fix operator = (Fix&); Fix operator = (double&); friend int operator == (Fix&, Fix& ); friend int operator != (Fix&, Fix&); friend int operator < (Fix&, Fix&); friend int operator <= (Fix&, Fix&); friend int operator > (Fix&, Fix&); friend int operator >= (Fix&, Fix&); Fix& operator + (); Fix operator - (); friend Fix operator + (Fix&, Fix&); friend Fix operator - (Fix&, Fix&); friend Fix operator * (Fix&, Fix&); friend Fix operator / (Fix&, Fix&); friend Fix operator * (Fix&, int); friend Fix operator * (int, Fix&); friend Fix operator % (Fix&, int); friend Fix operator << (Fix&, int); friend Fix operator >> (Fix&, int); #ifdef __GNUG__ friend Fix operator ? (Fix&, Fix&); // max #endif Fix operator += (Fix&); Fix operator -= (Fix&); Fix operator *= (Fix&); Fix operator /= (Fix&); Fix operator *= (int); Fix operator %= (int); Fix operator <<=(int); Fix operator >>=(int); friend char* Ftoa(Fix&, int width = Fix_default_print_width); friend Fix atoF(const char*, int len = Fix_default_length); friend istream& operator >> (istream&, Fix&); friend ostream& operator << (ostream&, Fix&); // built-in functions friend Fix abs(Fix); // absolute value friend int sgn(Fix&); // -1, 0, +1 friend Integer mantissa(Fix&); // integer representation friend double value(Fix&); // double value friend int length(Fix&); // field length friend void show(Fix&); // show contents // error handlers void error(const char* msg); // error handler void range_error(const char* msg); // range error handler // internal class functions friend void mask(_Fix); friend int compare(_Fix, _Fix = &_Frep_0); friend _Fix new_Fix(uint16); friend _Fix new_Fix(uint16, _Fix); friend _Fix new_Fix(uint16, double); friend _Fix copy(_Fix, _Fix); friend _Fix negate(_Fix, _Fix = NULL); friend _Fix add(_Fix, _Fix, _Fix = NULL); friend _Fix subtract(_Fix, _Fix, _Fix = NULL); friend _Fix multiply(_Fix, _Fix, _Fix = NULL); friend _Fix multiply(_Fix, int, _Fix = NULL); friend _Fix divide(_Fix, _Fix, _Fix = NULL, _Fix = NULL); friend _Fix shift(_Fix, int, _Fix = NULL); // non-operator versions for user friend void negate(Fix& x, Fix& r); friend void add(Fix& x, Fix& y, Fix& r); friend void subtract(Fix& x, Fix& y, Fix& r); friend void multiply(Fix& x, Fix& y, Fix& r); friend void divide(Fix& x, Fix& y, Fix& q, Fix& r); friend void shift(Fix& x, int y, Fix& r); }; // error handlers extern void default_Fix_error_handler(const char*), default_Fix_range_error_handler(const char*); extern one_arg_error_handler_t Fix_error_handler, Fix_range_error_handler; extern one_arg_error_handler_t set_Fix_error_handler(one_arg_error_handler_t f), set_Fix_range_error_handler(one_arg_error_handler_t f); typedef void (*Fix_peh)(_Fix&); extern Fix_peh Fix_overflow_handler; extern void Fix_overflow_saturate(_Fix&), Fix_overflow_wrap(_Fix&), Fix_overflow_warning_saturate(_Fix&), Fix_overflow_warning(_Fix&), Fix_overflow_error(_Fix&); extern Fix_peh set_overflow_handler(Fix_peh); extern int Fix_set_default_length(int); // function definitions inline void Fix::unique() { if ( rep->ref > 1 ) { rep->ref--; rep = new_Fix(rep->len,rep); } } inline void mask (_Fix x) { int n = x->len & 0x0f; if ( n ) x->s[x->siz - 1] &= 0xffff0000 >> n; } inline _Fix copy(_Fix from, _Fix to) { uint16 *ts = to->s, *fs = from->s; int ilim = to->siz < from->siz ? to->siz : from->siz; for ( int i=0; i < ilim; i++ ) *ts++ = *fs++; for ( ; i < to->siz; i++ ) *ts++ = 0; mask(to); return to; } inline Fix::Fix(_Fix f) { rep = f; } inline Fix::Fix() { rep = new_Fix(Fix_default_length); } inline Fix::Fix(int len) { if ( len < _Fix_min_length || len > _Fix_max_length ) error("illegal length in declaration"); rep = new_Fix((uint16 )len); } inline Fix::Fix(double& d) { rep = new_Fix(Fix_default_length,d); } inline Fix::Fix(Fix& y) { rep = y.rep; rep->ref++; } inline Fix::Fix(int len, Fix& y) { if ( len < _Fix_min_length || len > _Fix_max_length ) error("illegal length in declaration"); rep = new_Fix((uint16 )len,y.rep); } inline Fix::Fix(int len, _Frep* fr) { if ( len < 1 || len > 65535 ) error("illegal length in declaration"); rep = new_Fix((uint16 )len,fr); } inline Fix::Fix(int len, double& d) { if ( len < _Fix_min_length || len > _Fix_max_length ) error("illegal length in declaration"); rep = new_Fix((uint16 )len,d); } inline Fix::~Fix() { if ( --rep->ref <= 0 ) delete rep; } inline Fix Fix::operator = (Fix& y) { if ( rep->len == y.rep->len ) { ++y.rep->ref; if ( --rep->ref <= 0 ) delete rep; rep = y.rep; } else { unique(); copy(y.rep,rep); } return *this; } inline Fix Fix::operator = (double& d) { int oldlen = rep->len; if ( --rep->ref <= 0 ) delete rep; rep = new_Fix(oldlen,d); return *this; } inline int operator == (Fix& x, Fix& y) { return compare(x.rep, y.rep) == 0; } inline int operator != (Fix& x, Fix& y) { return compare(x.rep, y.rep) != 0; } inline int operator < (Fix& x, Fix& y) { return compare(x.rep, y.rep) < 0; } inline int operator <= (Fix& x, Fix& y) { return compare(x.rep, y.rep) <= 0; } inline int operator > (Fix& x, Fix& y) { return compare(x.rep, y.rep) > 0; } inline int operator >= (Fix& x, Fix& y) { return compare(x.rep, y.rep) >= 0; } inline Fix& Fix::operator + () { return *this; } inline Fix Fix::operator - () { _Fix r = negate(rep); return r; } inline Fix operator + (Fix& x, Fix& y) { _Fix r = add(x.rep, y.rep); return r; } inline Fix operator - (Fix& x, Fix& y) { _Fix r = subtract(x.rep, y.rep); return r; } inline Fix operator * (Fix& x, Fix& y) { _Fix r = multiply(x.rep, y.rep); return r; } inline Fix operator * (Fix& x, int y) { _Fix r = multiply(x.rep, y); return r; } inline Fix operator * (int y, Fix& x) { _Fix r = multiply(x.rep, y); return r; } inline Fix operator / (Fix& x, Fix& y) { _Fix r = divide(x.rep, y.rep); return r; } inline Fix Fix::operator += (Fix& y) { unique(); add(rep, y.rep, rep); return *this; } inline Fix Fix::operator -= (Fix& y) { unique(); subtract(rep, y.rep, rep); return *this; } inline Fix Fix::operator *= (Fix& y) { unique(); multiply(rep, y.rep, rep); return *this; } inline Fix Fix::operator *= (int y) { unique(); multiply(rep, y, rep); return *this; } inline Fix Fix::operator /= (Fix& y) { unique(); divide(rep, y.rep, rep); return *this; } inline Fix operator % (Fix& x, int y) { Fix r((int )x.rep->len + y, x); return r; } inline Fix operator << (Fix& x, int y) { _Fix rep = shift(x.rep, y); return rep; } inline Fix operator >> (Fix& x, int y) { _Fix rep = shift(x.rep, -y); return rep; } inline Fix Fix::operator <<= (int y) { unique(); shift(rep, y, rep); return *this; } inline Fix Fix::operator >>= (int y) { unique(); shift(rep, -y, rep); return *this; } #ifdef __GNUG__ inline Fix operator ? (Fix& x, Fix& y) { if ( compare(x.rep, y.rep) >= 0 ) return x; else return y; } #endif inline Fix abs(Fix x) { _Fix r = (compare(x.rep) >= 0 ? new_Fix(x.rep->len,x.rep) : negate(x.rep)); return r; } inline int sgn(Fix& x) { int a = compare(x.rep); return a == 0 ? 0 : (a > 0 ? 1 : -1); } inline int length(Fix& x) { return x.rep->len; } inline ostream& operator << (ostream& s, Fix& y) { return s << Ftoa(y); } inline void negate (Fix& x, Fix& r) { negate(x.rep, r.rep); } inline void add (Fix& x, Fix& y, Fix& r) { add(x.rep, y.rep, r.rep); } inline void subtract (Fix& x, Fix& y, Fix& r) { subtract(x.rep, y.rep, r.rep); } inline void multiply (Fix& x, Fix& y, Fix& r) { multiply(x.rep, y.rep, r.rep); } inline void divide (Fix& x, Fix& y, Fix& q, Fix& r) { divide(x.rep, y.rep, q.rep, r.rep); } inline void shift (Fix& x, int y, Fix& r) { shift(x.rep, y, r.rep); } #endif ) { return s << Ftoa(y); } inline void negate (Fix& x, Fixlibg++/g++-include/Geometric.h 644 473 0 2700 4677677720 11237 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Geometric_h #pragma once #define _Geometric_h #include class Geometric: public Random { protected: double pMean; public: Geometric(double mean, RNG *gen); double mean(); double mean(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Geometric::Geometric(double mean, RNG *gen) : (gen) { pMean = mean; } inline double Geometric::mean() { return pMean; } inline double Geometric::mean(double x) { double tmp = pMean; pMean = x; return tmp; } //#endif #endif #pragma once #define _Geometric_h #include class libg++/g++-include/HyperGeometric 644 473 0 3750 4677677720 12027 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _HyperGeometric_h #pragma once #define _HyperGeometric_h #include class HyperGeometric: public Random { protected: double pMean; double pVariance; double pP; void setState(); public: HyperGeometric(double mean, double variance, RNG *gen); double mean(); double mean(double x); double variance(); double variance(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline void HyperGeometric::setState() { double z = pVariance / (pMean * pMean); pP = 0.5 * (1.0 - sqrt((z - 1.0) / ( z + 1.0 ))); } inline HyperGeometric::HyperGeometric(double mean, double variance, RNG *gen) : (gen) { pMean = mean; pVariance = variance; setState(); } inline double HyperGeometric::mean() { return pMean; }; inline double HyperGeometric::mean(double x) { double t = pMean; pMean = x; setState(); return t; } inline double HyperGeometric::variance() { return pVariance; } inline double HyperGeometric::variance(double x) { double t = pVariance; pVariance = x; setState(); return t; } //#endif #endif 0 ))); } inline HyperGelibg++/g++-include/values.h 644 473 0 12640 4677677720 10644 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _values_h #pragma once #define _values_h 1 #define BITSPERBYTE 8 #define BITS(type) (BITSPERBYTE * (int)sizeof(type)) #define CHARBITS BITS(char) #define SHORTBITS BITS(short) #define INTBITS BITS(int) #define LONGBITS BITS(long) #define PTRBITS BITS(char*) #define DOUBLEBITS BITS(double) #define FLOATBITS BITS(float) #define MINSHORT ((short)(1 << (SHORTBITS - 1))) #define MININT (1 << (INTBITS - 1)) #define MINLONG (1L << (LONGBITS - 1)) #define MAXSHORT ((short)~MINSHORT) #define MAXINT (~MININT) #define MAXLONG (~MINLONG) #if defined(sun) || defined(hp300) || defined(hpux) #define MAXDOUBLE 1.79769313486231470e+308 #define MAXFLOAT ((float)3.40282346638528860e+38) #define MINDOUBLE 4.94065645841246544e-324 #define MINFLOAT ((float)1.40129846432481707e-45) #define _IEEE 1 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3)) #define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3)) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) #elif defined(sony) #define MAXDOUBLE 1.79769313486231470e+308 #define MAXFLOAT ((float)3.40282346638528860e+38) #define MINDOUBLE 2.2250738585072010e-308 #define MINFLOAT ((float)1.17549435e-38) #define _IEEE 1 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3)) #define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3)) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) #elif defined(sequent) extern double _maxdouble, _mindouble; extern float _maxfloat, _minfloat; #define MAXDOUBLE _maxdouble #define MAXFLOAT _maxfloat #define MINDOUBLE _mindouble #define MINFLOAT _minfloat #define _IEEE 1 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-(DMAXEXP - 3)) #define FMINEXP (-(FMAXEXP - 3)) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) #elif defined(i386) #define MAXDOUBLE 1.79769313486231570e+308 #define MAXFLOAT ((float)3.40282346638528860e+38) #define MINDOUBLE 2.22507385850720140e-308 #define MINFLOAT ((float)1.17549435082228750e-38) #define _IEEE 0 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-DMAXEXP) #define FMINEXP (-FMAXEXP) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) /* from Andrew Klossner */ #elif defined(m88k) /* These are "good" guesses ... I'll figure out the true mins and maxes later, at the time I find out the mins and maxes that the compiler can tokenize. */ #define MAXDOUBLE 1.79769313486231e+308 #define MAXFLOAT ((float)3.40282346638528e+38) #define MINDOUBLE 2.22507385850720e-308 #define MINFLOAT ((float)1.17549435082228e-38) #define _IEEE 1 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (1-DMAXEXP) #define FMINEXP (1-FMAXEXP) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) #elif defined(convex) #define MAXDOUBLE 8.9884656743115785e+306 #define MAXFLOAT ((float) 1.70141173e+38) #define MINDOUBLE 5.5626846462680035e-308 #define MINFLOAT ((float) 2.93873588e-39) #define _IEEE 0 #define _DEXPLEN 11 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-DMAXEXP) #define FMINEXP (-FMAXEXP) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) // #elif defined(vax) // use vax versions by default -- they seem to be the most conservative #else #define MAXDOUBLE 1.701411834604692293e+38 #define MINDOUBLE (2.938735877055718770e-39) #define MAXFLOAT 1.7014117331926443e+38 #define MINFLOAT 2.9387358770557188e-39 #define _IEEE 0 #define _DEXPLEN 8 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-DMAXEXP) #define FMINEXP (-FMAXEXP) #define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) #define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE) #endif #define DSIGNIF (DOUBLEBITS - _DEXPLEN + _HIDDENBIT - 1) #define FSIGNIF (FLOATBITS - _FEXPLEN + _HIDDENBIT - 1) #define DMAXPOWTWO ((double)(1L << LONGBITS -2)*(1L << DSIGNIF - LONGBITS +1)) #define FMAXPOWTWO ((float)(1L << FSIGNIF - 1)) #endif 0 #define _DEXPLEN 8 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-libg++/g++-include/Incremental.h 644 473 0 530 4677677720 11541 #ifndef Incremental_h #pragma once #define Incremental_h #define DECLARE_INIT_FUNCTION(USER_INIT_FUNCTION) \ static void USER_INIT_FUNCTION (); extern void (*_initfn)(); \ static struct xyzzy { xyzzy () {_initfn = USER_INIT_FUNCTION;}; \ ~xyzzy () {};} __2xyzzy; #else #error Incremental.h was not the first file included in this module #endif LONGBITS +1)) #define FMAXPOWTWO ((float)(1L << FSIGNIF - 1)) #endif 0 #define _DEXPLEN 8 #define _FEXPLEN 8 #define _HIDDENBIT 1 #define DMINEXP (-libg++/g++-include/Integer.h 644 473 0 54510 4677677721 10745 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Integer_h #pragma once #define _Integer_h 1 #include struct IntRep // internal Integer representations { unsigned short len; // current length unsigned short sz; // allocated space short sgn; // 1 means >= 0; 0 means < 0 unsigned short s[1]; // represented as ushort array starting here }; extern IntRep* Ialloc(IntRep*, const unsigned short *, int, int, int); extern IntRep* Icalloc(IntRep*, int); extern IntRep* Icopy_long(IntRep*, long); extern IntRep* Icopy(IntRep*, const IntRep*); extern IntRep* Iresize(IntRep*, int); extern IntRep* add(const IntRep*, int, const IntRep*, int, IntRep*); extern IntRep* add(const IntRep*, int, long, IntRep*); extern IntRep* multiply(const IntRep*, const IntRep*, IntRep*); extern IntRep* multiply(const IntRep*, long, IntRep*); extern IntRep* lshift(const IntRep*, long, IntRep*); extern IntRep* lshift(const IntRep*, const IntRep*, int, IntRep*); extern IntRep* bitop(const IntRep*, const IntRep*, IntRep*, char); extern IntRep* bitop(const IntRep*, long, IntRep*, char); extern IntRep* power(const IntRep*, long, IntRep*); extern IntRep* div(const IntRep*, const IntRep*, IntRep*); extern IntRep* mod(const IntRep*, const IntRep*, IntRep*); extern IntRep* div(const IntRep*, long, IntRep*); extern IntRep* mod(const IntRep*, long, IntRep*); extern IntRep* compl(const IntRep*, IntRep*); extern IntRep* abs(const IntRep*, IntRep*); extern IntRep* negate(const IntRep*, IntRep*); extern IntRep* pow(const IntRep*, long); extern IntRep* gcd(const IntRep*, const IntRep* y); extern int compare(const IntRep*, const IntRep*); extern int compare(const IntRep*, long); extern int ucompare(const IntRep*, const IntRep*); extern int ucompare(const IntRep*, long); extern char* Itoa(const IntRep* x, int base = 10, int width = 0); extern IntRep* atoIntRep(const char* s, int base = 10); extern long Itolong(const IntRep*); extern double Itodouble(const IntRep*); extern int Iislong(const IntRep*); extern int Iisdouble(const IntRep*); extern long lg(const IntRep*); class Integer { protected: IntRep* rep; public: Integer(); Integer(long); Integer(const Integer&); ~Integer(); void operator = (const Integer&); void operator = (long); // unary operations to self void operator ++ (); void operator -- (); void negate(); // negate in-place void abs(); // absolute-value in-place void complement(); // bitwise complement in-place // assignment-based operations void operator += (const Integer&); void operator -= (const Integer&); void operator *= (const Integer&); void operator /= (const Integer&); void operator %= (const Integer&); void operator <<=(const Integer&); void operator >>=(const Integer&); void operator &= (const Integer&); void operator |= (const Integer&); void operator ^= (const Integer&); void operator += (long); void operator -= (long); void operator *= (long); void operator /= (long); void operator %= (long); void operator <<=(long); void operator >>=(long); void operator &= (long); void operator |= (long); void operator ^= (long); // (constructive binary operations are inlined below) #ifdef __GNUG__ friend Integer operator ? (const Integer& x, const Integer& y); // max #endif // builtin Integer functions that must be friends friend long lg (const Integer&); // floor log base 2 of abs(x) friend double ratio(const Integer& x, const Integer& y); // return x/y as a double friend Integer gcd(const Integer&, const Integer&); friend int even(const Integer&); // true if even friend int odd(const Integer&); // true if odd friend int sign(const Integer&); // returns -1, 0, +1 friend void setbit(Integer& x, long b); // set b'th bit of x friend void clearbit(Integer& x, long b); // clear b'th bit friend int testbit(const Integer& x, long b); // return b'th bit // procedural versions of operators friend void abs(const Integer& x, Integer& dest); friend void negate(const Integer& x, Integer& dest); friend void complement(const Integer& x, Integer& dest); friend int compare(const Integer&, const Integer&); friend int ucompare(const Integer&, const Integer&); friend void add(const Integer& x, const Integer& y, Integer& dest); friend void sub(const Integer& x, const Integer& y, Integer& dest); friend void mul(const Integer& x, const Integer& y, Integer& dest); friend void div(const Integer& x, const Integer& y, Integer& dest); friend void mod(const Integer& x, const Integer& y, Integer& dest); friend void divide(const Integer& x, const Integer& y, Integer& q, Integer& r); friend void and(const Integer& x, const Integer& y, Integer& dest); friend void or(const Integer& x, const Integer& y, Integer& dest); friend void xor(const Integer& x, const Integer& y, Integer& dest); friend void lshift(const Integer& x, const Integer& y, Integer& dest); friend void rshift(const Integer& x, const Integer& y, Integer& dest); friend void pow(const Integer& x, const Integer& y, Integer& dest); friend int compare(const Integer&, long); friend int ucompare(const Integer&, long); friend void add(const Integer& x, long y, Integer& dest); friend void sub(const Integer& x, long y, Integer& dest); friend void mul(const Integer& x, long y, Integer& dest); friend void div(const Integer& x, long y, Integer& dest); friend void mod(const Integer& x, long y, Integer& dest); friend void divide(const Integer& x, long y, Integer& q, long& r); friend void and(const Integer& x, long y, Integer& dest); friend void or(const Integer& x, long y, Integer& dest); friend void xor(const Integer& x, long y, Integer& dest); friend void lshift(const Integer& x, long y, Integer& dest); friend void rshift(const Integer& x, long y, Integer& dest); friend void pow(const Integer& x, long y, Integer& dest); friend int compare(long, const Integer&); friend int ucompare(long, const Integer&); friend void add(long x, const Integer& y, Integer& dest); friend void sub(long x, const Integer& y, Integer& dest); friend void mul(long x, const Integer& y, Integer& dest); friend void and(long x, const Integer& y, Integer& dest); friend void or(long x, const Integer& y, Integer& dest); friend void xor(long x, const Integer& y, Integer& dest); // coercion & conversion int fits_in_long() const; int fits_in_double() const; operator long() const; operator double() const; friend char* Itoa(const Integer& x, int base = 10, int width = 0); friend Integer atoI(const char* s, int base = 10); friend istream& operator >> (istream& s, Integer& y); friend ostream& operator << (ostream& s, const Integer& y); // error detection int initialized() const; volatile void error(const char* msg) const; int OK() const; }; /* (These are declared inline below) int operator == (const Integer&, const Integer&); int operator == (const Integer&, long); int operator != (const Integer&, const Integer&); int operator != (const Integer&, long); int operator < (const Integer&, const Integer&); int operator < (const Integer&, long); int operator <= (const Integer&, const Integer&); int operator <= (const Integer&, long); int operator > (const Integer&, const Integer&); int operator > (const Integer&, long); int operator >= (const Integer&, const Integer&); int operator >= (const Integer&, long); Integer operator - (const Integer&); Integer operator ~ (const Integer&); Integer operator + (const Integer&, const Integer&); Integer operator + (const Integer&, long); Integer operator + (long, const Integer&); Integer operator - (const Integer&, const Integer&); Integer operator - (const Integer&, long); Integer operator - (long, const Integer&); Integer operator * (const Integer&, const Integer&); Integer operator * (const Integer&, long); Integer operator * (long, const Integer&); Integer operator / (const Integer&, const Integer&); Integer operator / (const Integer&, long); Integer operator % (const Integer&, const Integer&); Integer operator % (const Integer&, long); Integer operator << (const Integer&, const Integer&); Integer operator << (const Integer&, long); Integer operator >> (const Integer&, const Integer&); Integer operator >> (const Integer&, long); Integer operator & (const Integer&, const Integer&); Integer operator & (const Integer&, long); Integer operator & (long, const Integer&); Integer operator | (const Integer&, const Integer&); Integer operator | (const Integer&, long); Integer operator | (long, const Integer&); Integer operator ^ (const Integer&, const Integer&); Integer operator ^ (const Integer&, long); Integer operator ^ (long, const Integer&); Integer abs(const Integer&); // absolute value Integer sqr(const Integer&); // square Integer pow(const Integer& x, const Integer& y); Integer pow(const Integer& x, long y); Integer Ipow(long x, long y); // x to the y as Integer */ extern char* dec(const Integer& x, int width = 0); extern char* oct(const Integer& x, int width = 0); extern char* hex(const Integer& x, int width = 0); extern Integer sqrt(const Integer&); // floor of square root extern Integer lcm(const Integer& x, const Integer& y); // least common mult typedef Integer IntTmp; // for backward compatibility //#ifdef __OPTIMIZE__ inline Integer::Integer() :rep(0) {} inline Integer::Integer(long y) :rep(Icopy_long(0, y)) {} inline Integer::Integer(const Integer& y) :rep(Icopy(0, y.rep)) {} inline Integer::~Integer() { delete rep; } inline void Integer::operator = (const Integer& y) { rep = Icopy(rep, y.rep); } inline void Integer::operator = (long y) { rep = Icopy_long(rep, y); } inline Integer::operator long() const { return Itolong(rep); } inline int Integer::initialized() const { return rep != 0; } inline int Integer::fits_in_long() const { return Iislong(rep); } inline Integer::operator double() const { return Itodouble(rep); } inline int Integer::fits_in_double() const { return Iisdouble(rep); } // procedural versions inline int compare(const Integer& x, const Integer& y) { return compare(x.rep, y.rep); } inline int ucompare(const Integer& x, const Integer& y) { return ucompare(x.rep, y.rep); } inline int compare(const Integer& x, long y) { return compare(x.rep, y); } inline int ucompare(const Integer& x, long y) { return ucompare(x.rep, y); } inline int compare(long x, const Integer& y) { return -compare(y.rep, x); } inline int ucompare(long x, const Integer& y) { return -ucompare(y.rep, x); } inline void add(const Integer& x, const Integer& y, Integer& dest) { dest.rep = add(x.rep, 0, y.rep, 0, dest.rep); } inline void sub(const Integer& x, const Integer& y, Integer& dest) { dest.rep = add(x.rep, 0, y.rep, 1, dest.rep); } inline void mul(const Integer& x, const Integer& y, Integer& dest) { dest.rep = multiply(x.rep, y.rep, dest.rep); } inline void div(const Integer& x, const Integer& y, Integer& dest) { dest.rep = div(x.rep, y.rep, dest.rep); } inline void mod(const Integer& x, const Integer& y, Integer& dest) { dest.rep = mod(x.rep, y.rep, dest.rep); } inline void and(const Integer& x, const Integer& y, Integer& dest) { dest.rep = bitop(x.rep, y.rep, dest.rep, '&'); } inline void or(const Integer& x, const Integer& y, Integer& dest) { dest.rep = bitop(x.rep, y.rep, dest.rep, '|'); } inline void xor(const Integer& x, const Integer& y, Integer& dest) { dest.rep = bitop(x.rep, y.rep, dest.rep, '^'); } inline void lshift(const Integer& x, const Integer& y, Integer& dest) { dest.rep = lshift(x.rep, y.rep, 0, dest.rep); } inline void rshift(const Integer& x, const Integer& y, Integer& dest) { dest.rep = lshift(x.rep, y.rep, 1, dest.rep); } inline void pow(const Integer& x, const Integer& y, Integer& dest) { dest.rep = power(x.rep, long(y), dest.rep); // not incorrect } inline void add(const Integer& x, long y, Integer& dest) { dest.rep = add(x.rep, 0, y, dest.rep); } inline void sub(const Integer& x, long y, Integer& dest) { dest.rep = add(x.rep, 0, -y, dest.rep); } inline void mul(const Integer& x, long y, Integer& dest) { dest.rep = multiply(x.rep, y, dest.rep); } inline void div(const Integer& x, long y, Integer& dest) { dest.rep = div(x.rep, y, dest.rep); } inline void mod(const Integer& x, long y, Integer& dest) { dest.rep = mod(x.rep, y, dest.rep); } inline void and(const Integer& x, long y, Integer& dest) { dest.rep = bitop(x.rep, y, dest.rep, '&'); } inline void or(const Integer& x, long y, Integer& dest) { dest.rep = bitop(x.rep, y, dest.rep, '|'); } inline void xor(const Integer& x, long y, Integer& dest) { dest.rep = bitop(x.rep, y, dest.rep, '^'); } inline void lshift(const Integer& x, long y, Integer& dest) { dest.rep = lshift(x.rep, y, dest.rep); } inline void rshift(const Integer& x, long y, Integer& dest) { dest.rep = lshift(x.rep, -y, dest.rep); } inline void pow(const Integer& x, long y, Integer& dest) { dest.rep = power(x.rep, y, dest.rep); } inline void abs(const Integer& x, Integer& dest) { dest.rep = abs(x.rep, dest.rep); } inline void negate(const Integer& x, Integer& dest) { dest.rep = negate(x.rep, dest.rep); } inline void complement(const Integer& x, Integer& dest) { dest.rep = compl(x.rep, dest.rep); } inline void add(long x, const Integer& y, Integer& dest) { dest.rep = add(y.rep, 0, x, dest.rep); } inline void sub(long x, const Integer& y, Integer& dest) { dest.rep = add(y.rep, 1, x, dest.rep); } inline void mul(long x, const Integer& y, Integer& dest) { dest.rep = multiply(y.rep, x, dest.rep); } inline void and(long x, const Integer& y, Integer& dest) { dest.rep = bitop(y.rep, x, dest.rep, '&'); } inline void or(long x, const Integer& y, Integer& dest) { dest.rep = bitop(y.rep, x, dest.rep, '|'); } inline void xor(long x, const Integer& y, Integer& dest) { dest.rep = bitop(y.rep, x, dest.rep, '^'); } // operator versions inline int operator == (const Integer& x, const Integer& y) { return compare(x, y) == 0; } inline int operator == (const Integer& x, long y) { return compare(x, y) == 0; } inline int operator != (const Integer& x, const Integer& y) { return compare(x, y) != 0; } inline int operator != (const Integer& x, long y) { return compare(x, y) != 0; } inline int operator < (const Integer& x, const Integer& y) { return compare(x, y) < 0; } inline int operator < (const Integer& x, long y) { return compare(x, y) < 0; } inline int operator <= (const Integer& x, const Integer& y) { return compare(x, y) <= 0; } inline int operator <= (const Integer& x, long y) { return compare(x, y) <= 0; } inline int operator > (const Integer& x, const Integer& y) { return compare(x, y) > 0; } inline int operator > (const Integer& x, long y) { return compare(x, y) > 0; } inline int operator >= (const Integer& x, const Integer& y) { return compare(x, y) >= 0; } inline int operator >= (const Integer& x, long y) { return compare(x, y) >= 0; } inline Integer operator + (const Integer& x, const Integer& y) return r { add(x, y, r); } inline Integer operator + (const Integer& x, long y) return r { add(x, y, r); } inline Integer operator + (long x, const Integer& y) return r { add(x, y, r); } inline void Integer::operator += (const Integer& y) { add(*this, y, *this); } inline void Integer::operator += (long y) { add(*this, y, *this); } inline void Integer::operator ++ () { add(*this, 1, *this); } inline Integer operator - (const Integer& x, const Integer& y) return r { sub(x, y, r); } inline Integer operator - (const Integer& x, long y) return r { sub(x, y, r); } inline Integer operator - (long x, const Integer& y) return r { sub(x, y, r); } inline void Integer::operator -= (const Integer& y) { sub(*this, y, *this); } inline void Integer::operator -= (long y) { sub(*this, y, *this); } inline void Integer::operator -- () { add(*this, -1, *this); } inline Integer operator * (const Integer& x, const Integer& y) return r { mul(x, y, r); } inline Integer operator * (const Integer& x, long y) return r { mul(x, y, r); } inline Integer operator * (long x, const Integer& y) return r { mul(x, y, r); } inline void Integer::operator *= (const Integer& y) { mul(*this, y, *this); } inline void Integer::operator *= (long y) { mul(*this, y, *this); } inline Integer sqr(const Integer& x) return r { mul(x, x, r); } inline Integer operator & (const Integer& x, const Integer& y) return r { and(x, y, r); } inline Integer operator & (const Integer& x, long y) return r { and(x, y, r); } inline Integer operator & (long x, const Integer& y) return r { and(x, y, r); } inline void Integer::operator &= (const Integer& y) { and(*this, y, *this); } inline void Integer::operator &= (long y) { and(*this, y, *this); } inline Integer operator | (const Integer& x, const Integer& y) return r { or(x, y, r); } inline Integer operator | (const Integer& x, long y) return r { or(x, y, r); } inline Integer operator | (long x, const Integer& y) return r { or(x, y, r); } inline void Integer::operator |= (const Integer& y) { or(*this, y, *this); } inline void Integer::operator |= (long y) { or(*this, y, *this); } inline Integer operator ^ (const Integer& x, const Integer& y) return r { xor(x, y, r); } inline Integer operator ^ (const Integer& x, long y) return r { xor(x, y, r); } inline Integer operator ^ (long x, const Integer& y) return r { xor(x, y, r); } inline void Integer::operator ^= (const Integer& y) { xor(*this, y, *this); } inline void Integer::operator ^= (long y) { xor(*this, y, *this); } inline Integer operator / (const Integer& x, const Integer& y) return r { div(x, y, r); } inline Integer operator / (const Integer& x, long y) return r { div(x, y, r); } inline void Integer::operator /= (const Integer& y) { div(*this, y, *this); } inline void Integer::operator /= (long y) { div(*this, y, *this); } inline Integer operator % (const Integer& x, const Integer& y) return r { mod(x, y, r); } inline Integer operator % (const Integer& x, long y) return r { mod(x, y, r); } inline void Integer::operator %= (const Integer& y) { mod(*this, y, *this); } inline void Integer::operator %= (long y) { mod(*this, y, *this); } inline Integer operator << (const Integer& x, const Integer& y) return r { lshift(x, y, r); } inline Integer operator << (const Integer& x, long y) return r { lshift(x, y, r); } inline void Integer::operator <<= (const Integer& y) { lshift(*this, y, *this); } inline void Integer::operator <<= (long y) { lshift(*this, y, *this); } inline Integer operator >> (const Integer& x, const Integer& y) return r; { rshift(x, y, r); } inline Integer operator >> (const Integer& x, long y) return r { rshift(x, y, r); } inline void Integer::operator >>= (const Integer& y) { rshift(*this, y, *this); } inline void Integer::operator >>= (long y) { rshift(*this, y, *this); } #ifdef __GNUG__ inline Integer operator ? (const Integer& x, const Integer& y) { return (compare(x.rep, y.rep) >= 0)? x : y; } #endif inline Integer pow(const Integer& x, long y) return r { pow(x, y, r); } inline Integer Ipow(long x, long y) return r(x) { pow(r, y, r); } inline Integer pow(const Integer& x, const Integer& y) return r { pow(x, y, r); } inline Integer abs(const Integer& x) return r { abs(x, r); } inline void Integer::abs() { ::abs(*this, *this); } inline void Integer::negate() { ::negate(*this, *this); } inline Integer operator - (const Integer& x) return r { negate(x, r); } inline void Integer::complement() { ::complement(*this, *this); } inline Integer operator ~ (const Integer& x) return r { complement(x, r); } inline int sign(const Integer& x) { return (x.rep->len == 0) ? 0 : ( (x.rep->sgn == 1) ? 1 : -1 ); } inline int even(const Integer& y) { return y.rep->len == 0 || !(y.rep->s[0] & 1); } inline int odd(const Integer& y) { return y.rep->len > 0 && (y.rep->s[0] & 1); } inline char* Itoa(const Integer& y, int base, int width) { return Itoa(y.rep, base, width); } inline Integer atoI(const char* s, int base) return r { r.rep = atoIntRep(s, base); } inline ostream& operator << (ostream& s, const Integer& y) { return s << Itoa(y.rep); } inline Integer gcd(const Integer& x, const Integer& y) return r { r.rep = gcd(x.rep, y.rep); } inline long lg(const Integer& x) { return lg(x.rep); } //#endif #endif r& y) { return y.rep->len > 0 && (y.rep->s[0] & 1); } inline char* Itoa(const Integer& y, int base, int width) { return Itoa(y.rep, base, width); } inline Integer atoI(const chalibg++/g++-include/LogNormal.h 644 473 0 4023 4677677721 11214 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _LogNormal_h #pragma once #define _LogNormal_h #include "Normal.h" class LogNormal: public Normal { protected: double logMean; double logVariance; void setState(); public: LogNormal(double mean, double variance, RNG *gen); inline double mean(); inline double mean(double x); inline double variance(); inline double variance(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline void LogNormal::setState() { double m2 = logMean * logMean; pMean = log(m2 / sqrt(logVariance + m2) ); pVariance = log((sqrt(logVariance + m2)/m2 )); } inline LogNormal::LogNormal(double mean, double variance, RNG *gen) : (mean, variance, gen) { logMean = mean; logVariance = variance; setState(); } inline double LogNormal::mean() { return logMean; } inline double LogNormal::mean(double x) { double t=logMean; logMean = x; setState(); return t; } inline double LogNormal::variance() { return logVariance; } inline double LogNormal::variance(double x) { double t=logVariance; logVariance = x; setState(); return t; } #endif e LogNormal::LogNormal(double mean, double variance, RNG *gen) : (mean, variance, gen) { logMean = mean; logVariance = variance; setState(); } inline double LogNormal::mean() { return logMean; } inline double LogNormal::mean(double x) { double t=logMean; logMean = x; setState(); return t; } inline double LogNormal::variance() { return logVariance; } inline double LogNormal::variance(double x) { double t=logVariance; logVariance = x; setState(); rlibg++/g++-include/regex.h 644 473 0 31174 4677677721 10463 /* Definitions for data structures callers pass the regex library. Copyright (C) 1985 Free Software Foundation, Inc. NO WARRANTY BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. GENERAL PUBLIC LICENSE TO COPY 1. You may copy and distribute verbatim copies of this source file as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright notice "Copyright (C) 1985 Free Software Foundation, Inc."; and include following the copyright notice a verbatim copy of the above disclaimer of warranty and of this License. You may charge a distribution fee for the physical act of transferring a copy. 2. You may modify your copy or copies of this source file or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains or is a derivative of this program or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third parties, at your option). c) You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms. 3. You may copy and distribute this program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs. 4. You may not copy, sublicense, distribute or transfer this program except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer this program is void and your rights to use the program under this License agreement shall be automatically terminated. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated so long as such parties remain in full compliance. 5. If you wish to incorporate parts of this program into other free programs whose distribution conditions are different, write to the Free Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We 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. 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! */ /* Define number of parens for which we record the beginnings and ends. This affects how much space the `struct re_registers' type takes up. */ #ifndef RE_NREGS #define RE_NREGS 10 #endif /* These bits are used in the obscure_syntax variable to choose among alternative regexp syntaxes. */ /* 1 means plain parentheses serve as grouping, and backslash parentheses are needed for literal searching. 0 means backslash-parentheses are grouping, and plain parentheses are for literal searching. */ #define RE_NO_BK_PARENS 1 /* 1 means plain | serves as the "or"-operator, and \| is a literal. 0 means \| serves as the "or"-operator, and | is a literal. */ #define RE_NO_BK_VBAR 2 /* 0 means plain + or ? serves as an operator, and \+, \? are literals. 1 means \+, \? are operators and plain +, ? are literals. */ #define RE_BK_PLUS_QM 4 /* 1 means | binds tighter than ^ or $. 0 means the contrary. */ #define RE_TIGHT_VBAR 8 /* 1 means treat \n as an _OR operator 0 means treat it as a normal character */ #define RE_NEWLINE_OR 16 /* 0 means that a special characters (such as *, ^, and $) always have their special meaning regardless of the surrounding context. 1 means that special characters may act as normal characters in some contexts. Specifically, this applies to: ^ - only special at the beginning, or after ( or | $ - only special at the end, or before ) or | *, +, ? - only special when not after the beginning, (, or | */ #define RE_CONTEXT_INDEP_OPS 32 /* Now define combinations of bits for the standard possibilities. */ #define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS) #define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR) #define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) #define RE_SYNTAX_EMACS 0 /* This data structure is used to represent a compiled pattern. */ struct re_pattern_buffer { char *buffer; /* Space holding the compiled pattern commands. */ int allocated; /* Size of space that buffer points to */ int used; /* Length of portion of buffer actually occupied */ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ /* re_search uses the fastmap, if there is one, to skip quickly over totally implausible characters */ char *translate; /* Translate table to apply to all characters before comparing. Or zero for no translation. The translation is applied to a pattern when it is compiled and to data when it is matched. */ char fastmap_accurate; /* Set to zero when a new pattern is stored, set to one when the fastmap is updated from it. */ char can_be_null; /* Set to one by compiling fastmap if this pattern might match the null string. It does not necessarily match the null string in that case, but if this is zero, it cannot. 2 as value means can match null string but at end of range or before a character listed in the fastmap. */ }; /* Structure to store "register" contents data in. Pass the address of such a structure as an argument to re_match, etc., if you want this information back. start[i] and end[i] record the string matched by \( ... \) grouping i, for i from 1 to RE_NREGS - 1. start[0] and end[0] record the entire string matched. */ struct re_registers { int start[RE_NREGS]; int end[RE_NREGS]; }; /* These are the command codes that appear in compiled regular expressions, one per byte. Some command codes are followed by argument bytes. A command code can specify any interpretation whatever for its arguments. Zero-bytes may appear in the compiled regular expression. */ enum regexpcode { unused, exactn, /* followed by one byte giving n, and then by n literal bytes */ begline, /* fails unless at beginning of line */ endline, /* fails unless at end of line */ jump, /* followed by two bytes giving relative address to jump to */ on_failure_jump, /* followed by two bytes giving relative address of place to resume at in case of failure. */ finalize_jump, /* Throw away latest failure point and then jump to address. */ maybe_finalize_jump, /* Like jump but finalize if safe to do so. This is used to jump back to the beginning of a repeat. If the command that follows this jump is clearly incompatible with the one at the beginning of the repeat, such that we can be sure that there is no use backtracking out of repetitions already completed, then we finalize. */ dummy_failure_jump, /* jump, and push a dummy failure point. This failure point will be thrown away if an attempt is made to use it for a failure. A + construct makes this before the first repeat. */ anychar, /* matches any one character */ charset, /* matches any one char belonging to specified set. First following byte is # bitmap bytes. Then come bytes for a bit-map saying which chars are in. Bits in each byte are ordered low-bit-first. A character is in the set if its bit is 1. A character too large to have a bit in the map is automatically not in the set */ charset_not, /* similar but match any character that is NOT one of those specified */ start_memory, /* starts remembering the text that is matched and stores it in a memory register. followed by one byte containing the register number. Register numbers must be in the range 0 through NREGS. */ stop_memory, /* stops remembering the text that is matched and stores it in a memory register. followed by one byte containing the register number. Register numbers must be in the range 0 through NREGS. */ duplicate, /* match a duplicate of something remembered. Followed by one byte containing the index of the memory register. */ before_dot, /* Succeeds if before dot */ at_dot, /* Succeeds if at dot */ after_dot, /* Succeeds if after dot */ begbuf, /* Succeeds if at beginning of buffer */ endbuf, /* Succeeds if at end of buffer */ wordchar, /* Matches any word-constituent character */ notwordchar, /* Matches any char that is not a word-constituent */ wordbeg, /* Succeeds if at word beginning */ wordend, /* Succeeds if at word end */ wordbound, /* Succeeds if at a word boundary */ notwordbound, /* Succeeds if not at a word boundary */ syntaxspec, /* Matches any character whose syntax is specified. followed by a byte which contains a syntax code, Sword or such like */ notsyntaxspec /* Matches any character whose syntax differs from the specified. */ }; extern char *re_compile_pattern (char*, int, struct re_pattern_buffer*); /* Is this really advertised? */ extern void re_compile_fastmap (struct re_pattern_buffer*); extern int re_search(struct re_pattern_buffer*, char*, int, int, int, struct re_registers*); extern int re_search_2 (struct re_pattern_buffer*, char*, int, char*, int, int, int, struct re_registers*, int); extern int re_match (struct re_pattern_buffer*, char*, int, int, struct re_registers*); extern int re_match_2 (struct re_pattern_buffer*, unsigned char*, int, unsigned char*, int, int, struct re_registers*, int); /* 4.2 bsd compatibility (yuck) */ extern char *re_comp (char*); extern int re_exec (char*); #ifdef SYNTAX_TABLE extern char *re_syntax_table; #endif nt, struct re_registers*); extern int re_search_2 (struct re_pattern_buffer*, char*, int, char*, int, int, int, struct re_registers*, int); extern int re_match (struct re_pattern_buffer*, char*, int, int, struct re_registers*); extern int re_match_2 (struct re_pattern_buffer*, unsigned char*, int, unsigned char*, int, int, struct re_registers*, int); /* 4.2 bsd compatibility (yulibg++/g++-include/MLCG.h 644 473 0 3504 4677677721 10047 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _MLCG_h #define _MLCG_h 1 #pragma once #include #include // // Multiplicative Linear Conguential Generator // class MLCG : public RNG { long initialSeedOne; long initialSeedTwo; long seedOne; long seedTwo; protected: public: MLCG(long seed1 = 0, long seed2 = 1); // // Return a long-words word of random bits // virtual unsigned long asLong(); virtual void reset(); long seed1(); void seed1(long); long seed2(); void seed2(long); void reseed(long, long); }; inline long MLCG::seed1() { return(seedOne); } inline void MLCG::seed1(long s) { initialSeedOne = s; reset(); } inline long MLCG::seed2() { return(seedTwo); } inline void MLCG::seed2(long s) { initialSeedTwo = s; reset(); } inline void MLCG::reseed(long s1, long s2) { initialSeedOne = s1; initialSeedTwo = s2; reset(); } #endif ); virtual void reset(); long seed1(); void seed1(long); long seed2(); void seed2(long); void reseed(long, long); }; inline long MLCG::seed1() { return(seedOnelibg++/g++-include/NegativeExpntl 644 473 0 3030 4677677721 12026 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _NegativeExpntl_h #pragma once #define _NegativeExpntl_h 1 // // Negative Exponential Random Numbers // // #include class NegativeExpntl: public Random { protected: double pMean; public: NegativeExpntl(double xmean, RNG *gen); double mean(); double mean(double x); virtual double operator()(); }; //ifdef __OPTIMIZE__ inline NegativeExpntl::NegativeExpntl(double xmean, RNG *gen) : (gen) { pMean = xmean; } inline double NegativeExpntl::mean() { return pMean; } inline double NegativeExpntl::mean(double x) { double t = pMean; pMean = x; return t; } //endif #endif rs // // #include class NegativeExpntl: public Random { protected: double pMean; public: NegativeExpntl(double xmean, RNG *gen); double mean(); double mean(double x); virtual double operator()(); }; //ifdef __OPTIMIZE__ inline NegativeExpntl::NegativeExpntl(double xmean, RNG *gen) : (gen) { pMean = xmean; } inline double NegativeExpntl::mean() { return pMean; } inline double NegativeExpntl::mean(double x) { double t = pMean; pMean = x; retulibg++/g++-include/Normal.h 644 473 0 3543 4677677721 10560 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Normal_h #pragma once #define _Normal_h #include class Normal: public Random { char haveCachedNormal; double cachedNormal; protected: double pMean; double pVariance; double pStdDev; public: Normal(double xmean, double xvariance, RNG *gen); double mean(); double mean(double x); double variance(); double variance(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Normal::Normal(double xmean, double xvariance, RNG *gen) : (gen) { pMean = xmean; pVariance = xvariance; pStdDev = sqrt(pVariance); haveCachedNormal = 0; } inline double Normal::mean() { return pMean; }; inline double Normal::mean(double x) { double t=pMean; pMean = x; return t; } inline double Normal::variance() { return pVariance; } inline double Normal::variance(double x) { double t=pVariance; pVariance = x; pStdDev = sqrt(pVariance); return t; }; //#endif #endif __OPTIMIZE__ inline Normal::Normal(double xmean, double xvariance, RNG *gen) : (gen) { pMean = xmean; pVariance = xvariance; pStdDev = sqrt(pVariance);libg++/g++-include/Obstack.h 644 473 0 10536 4677677722 10737 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Obstack_h #pragma once #define _Obstack_h 1 #include class Obstack { struct _obstack_chunk { char* limit; _obstack_chunk* prev; char contents[4]; }; protected: long chunksize; _obstack_chunk* chunk; char* objectbase; char* nextfree; char* chunklimit; int alignmentmask; void _free(void* obj); void newchunk(int size); public: Obstack(int size = 4080, int alignment = 4); // 4080=4096-mallocslop ~Obstack(); void* base(); void* next_free(); int alignment_mask(); int chunk_size(); int size(); int room(); int contains(void* p); // does Obstack hold pointer p? void grow(const void* data, int size); void grow(const void* data, int size, char terminator); void grow(const char* s); void grow(char c); void grow_fast(char c); void blank(int size); void blank_fast(int size); void* finish(); void* finish(char terminator); void* copy(const void* data, int size); void* copy(const void* data, int size, char terminator); void* copy(const char* s); void* copy(char c); void* alloc(int size); void free(void* obj); void shrink(int size = 1); // suggested by ken@cs.rochester.edu int OK(); // rep invariant }; //#ifdef __OPTIMIZE__ inline Obstack::~Obstack() { _free(0); } inline void* Obstack::base() { return objectbase; } inline void* Obstack::next_free() { return nextfree; } inline int Obstack::alignment_mask() { return alignmentmask; } inline int Obstack::chunk_size() { return chunksize; } inline int Obstack::size() { return nextfree - objectbase; } inline int Obstack::room() { return chunklimit - nextfree; } inline void Obstack:: grow(const void* data, int size) { if (nextfree+size > chunklimit) newchunk(size); bcopy(data, nextfree, size); nextfree += size; } inline void Obstack:: grow(const void* data, int size, char terminator) { if (nextfree+size+1 > chunklimit) newchunk(size+1); bcopy(data, nextfree, size); nextfree += size; *(nextfree)++ = terminator; } inline void Obstack:: grow(const char* s) { grow((void*)s, strlen(s), 0); } inline void Obstack:: grow(char c) { if (nextfree+1 > chunklimit) newchunk(1); *(nextfree)++ = c; } inline void Obstack:: blank(int size) { if (nextfree+size > chunklimit) newchunk(size); nextfree += size; } inline void* Obstack::finish(char terminator) { grow(terminator); return finish(); } inline void* Obstack::copy(const void* data, int size) { grow (data, size); return finish(); } inline void* Obstack::copy(const void* data, int size, char terminator) { grow(data, size, terminator); return finish(); } inline void* Obstack::copy(const char* s) { grow((void*)s, strlen(s), 0); return finish(); } inline void* Obstack::copy(char c) { grow(c); return finish(); } inline void* Obstack::alloc(int size) { blank(size); return finish(); } inline void Obstack:: free(void* obj) { if (obj >= (void*)chunk && obj<(void*)chunklimit) nextfree = objectbase = (char *) obj; else _free(obj); } inline void Obstack:: grow_fast(char c) { *(nextfree)++ = c; } inline void Obstack:: blank_fast(int size) { nextfree += size; } inline void Obstack:: shrink(int size) // from ken@cs.rochester.edu { if (nextfree >= objectbase + size) nextfree -= size; } //#endif #endif ck::alloc(int size) { blank(size); return finish(); } inline void Obstack:: free(void* obj) { if (obj >= (void*)chunk && obj<(void*)chunklimit) nlibg++/g++-include/Pix.h 644 473 0 110 4677677722 10034 #ifndef _Pix_h #pragma once #define _Pix_h 1 typedef void* Pix; #endif void Obstack:: grow_fast(char c) { *(nextfree)++ = c; } inline void Obstack:: blank_fast(int size) { nextfree += size; } inline void Obstack:: shrink(int size) // from ken@cs.rochester.edu { if (nextfree >= objectbase + size) nextfree -= size; } //#endif #endif ck::alloc(int size) { blank(size); return finish(); } inline void Obstack:: free(void* obj) { if (obj >= (void*)chunk && obj<(void*)chunklimit) nlibg++/g++-include/PlotFile.h 644 473 0 6416 4677677722 11051 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* a very simple implementation of a class to output unix "plot" format plotter files. See corresponding unix man pages for more details. */ #ifndef _PlotFile_h #pragma once #define _PlotFile_h #include /* Some plot libraries have the `box' command to draw boxes. Some don't. `box' is included here via moves & lines to allow both possiblilties. */ class PlotFile : private File { protected: PlotFile& cmd(char c); PlotFile& operator << (const int x); PlotFile& operator << (const char *s); public: File::close; File::raw; File::remove; File::filedesc; File::is_open; File::iocount; File::error; File::name; File::setname; File::rdstate; File::eof; File::fail; File::bad; File::good; File::clear; File::failif; File::writable; File::readable; PlotFile(); PlotFile(const char* filename, io_mode m, access_mode a); PlotFile(const char* filename, const char* m); PlotFile(int filedesc, io_mode m = io_writeonly); PlotFile(FILE* fileptr); ~PlotFile(); operator void*(); PlotFile& open(const char* filename, const io_mode m, const access_mode a); PlotFile& open(const char* filename, const char* m); PlotFile& open(const int filedesc, const io_mode m); PlotFile& open(FILE* fileptr); PlotFile& setbuf(const int buffer_kind); // vals: _IONBF, _IOFBF, _IOLBF PlotFile& setbuf(const int size, char* buf); PlotFile& arc(const int xi, const int yi, const int x0, const int y0, const int x1, const int y1); PlotFile& box(const int x0, const int y0, const int x1, const int y1); PlotFile& circle(const int x, const int y, const int r); PlotFile& cont(const int xi, const int yi); PlotFile& dot(const int xi, const int yi, const int dx, int n, const int* pat); PlotFile& erase(); PlotFile& label(const char* s); PlotFile& line(const int x0, const int y0, const int x1, const int y1); PlotFile& linemod(const char* s); PlotFile& move(const int xi, const int yi); PlotFile& point(const int xi, const int yi); PlotFile& space(const int x0, const int y0, const int x1, const int y1); }; #endif ont(const int xi, const int yi); PlotFile& dot(const int xi, const int yi, const int dx, int n, const int* pat); PlotFile& erase(); PlotFile& label(const char* s); PlotFile& line(const int x0, const int y0, libg++/g++-include/Poisson.h 644 473 0 2656 4677677722 10767 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Poisson_h #pragma once #define _Poisson_h #include class Poisson: public Random { protected: double pMean; public: Poisson(double mean, RNG *gen); double mean(); double mean(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Poisson::Poisson(double mean, RNG *gen) : (gen) { pMean = mean; } inline double Poisson::mean() { return pMean; } inline double Poisson::mean(double x) { double t = pMean; pMean = x; return t; } //#endif #endif fndef _Poisson_h #pragma once #define _Poisson_h #include class Poislibg++/g++-include/RNG.h 644 473 0 4367 4677677722 7764 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RNG_h #pragma once #define _RNG_h 1 #pragma once #include #include union PrivateRNGSingleType { // used to access floats as unsigneds float s; unsigned long u; }; union PrivateRNGDoubleType { // used to access doubles as unsigneds double d; unsigned long u[2]; }; // // Base class for Random Number Generators. See ACG and MLCG for instances. // class RNG { static PrivateRNGSingleType singleMantissa; // mantissa bit vector static PrivateRNGDoubleType doubleMantissa; // mantissa bit vector public: RNG(); // // Return a long-words word of random bits // virtual unsigned long asLong() = 0; virtual void reset() = 0; // // Return random bits converted to either a float or a double // float asFloat(); double asDouble(); }; inline float RNG::asFloat() { PrivateRNGSingleType result; result.s = 1.0; result.u |= (asLong() & singleMantissa.u); result.s -= 1.0; assert( result.s < 1.0 && result.s >= 0); return( result.s ); } inline double RNG::asDouble() { PrivateRNGDoubleType result; result.d = 1.0; result.u[0] |= (asLong() & doubleMantissa.u[0]); result.u[1] |= (asLong() & doubleMantissa.u[1]); result.d -= 1.0; assert( result.d < 1.0 && result.d >= 0); return( result.d ); } #endif ne float RNG::asFloat() { PrivateRNGSingleType result; result.s = 1.0; result.u |= (asLong() & singleMantissa.u); result.s -= 1.0; assert( result.s < 1.0 && result.s >= 0); return( result.s ); } inline double RNG::asDouble() { PrivateRlibg++/g++-include/Random.h 644 473 0 2576 4677677722 10556 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Random_h #pragma once #define _Random_h 1 #pragma once #include #include "RNG.h" class Random { protected: RNG *pGenerator; public: Random(RNG *generator); virtual double operator()() = 0; RNG *generator(); void generator(RNG *p); }; inline Random::Random(RNG *gen) { pGenerator = gen; } inline RNG *Random::generator() { return(pGenerator); } inline void Random::generator(RNG *p) { pGenerator = p; } #endif notice must be preserved on all copies. */ #ifndef _Random_h #pragma once #define _Random_h 1 #pragma once #include #libg++/g++-include/RandomInterval 644 473 0 3513 4677677722 12025 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RandomInterval_h #pragma once #define _RandomInterval_h 1 #include // // The interval [lo..hi] // class RandomInterval: public Random { protected: double pLow; double pHigh; public: RandomInterval(double low, double high, RNG *gen); double low(); double low(double x); double high(); double high(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline RandomInterval::RandomInterval(double low, double high, RNG *gen) : (gen) { if (low < high) { pLow = low; pHigh = high; } else { pLow = high; pHigh = low; } } inline double RandomInterval::low() { return pLow; } inline double RandomInterval::low(double x) { double tmp = pLow; pLow = x; return tmp; } inline double RandomInterval::high() { return pHigh; } inline double RandomInterval::high(double x) { double tmp = pHigh; pHigh = x; return tmp; } //#endif #endif IZE__ inline RandomInterval::RandomInterval(double low, double high, RNG *gen) : (gen) { if (low < high) { pLow = low; pHigh = high; } else { pLow = high; pHigh libg++/g++-include/RandomRange.h 644 473 0 3451 4677677723 11525 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RandomRange_h #pragma once #define _RandomRange_h 1 #include // // The interval [lo..hi) // class RandomRange: public Random { protected: double pLow; double pHigh; public: RandomRange(double low, double high, RNG *gen); double low(); double low(double x); double high(); double high(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline RandomRange::RandomRange(double low, double high, RNG *gen) : (gen) { if (low > high) { pHigh = low; pLow = high; } else { pLow = low; pHigh = high; } } inline double RandomRange::low() { return pLow; } inline double RandomRange::low(double x) { double tmp = pLow; pLow = x; return tmp; } inline double RandomRange::high() { return pHigh; } inline double RandomRange::high(double x) { double tmp = pHigh; pHigh = x; return tmp; } //#endif #endif }; //#ifdef __OPTIMIZE__ inline RandomRange::RandomRange(double low, double high, RNG *gen) : (gen) { if (low > high) { pHigh = low; pLow = high; } else { pLow = low; pHigh = high; } } inline dlibg++/g++-include/Rational.h 644 473 0 14751 4677677723 11126 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Rational_h #pragma once #define _Rational_h 1 #include #include class Rational { protected: Integer num; Integer den; void normalize(); public: Rational(); Rational(double); Rational(long n, long d = 1); Rational(const Integer& n); Rational(const Integer& n, const Integer& d); Rational(const Rational&); ~Rational(); void operator = (const Rational& y); friend int operator == (const Rational& x, const Rational& y); friend int operator != (const Rational& x, const Rational& y); friend int operator < (const Rational& x, const Rational& y); friend int operator <= (const Rational& x, const Rational& y); friend int operator > (const Rational& x, const Rational& y); friend int operator >= (const Rational& x, const Rational& y); friend Rational operator + (const Rational& x, const Rational& y); friend Rational operator - (const Rational& x, const Rational& y); friend Rational operator * (const Rational& x, const Rational& y); friend Rational operator / (const Rational& x, const Rational& y); void operator += (const Rational& y); void operator -= (const Rational& y); void operator *= (const Rational& y); void operator /= (const Rational& y); #ifdef __GNUG__ friend Rational operator ? (const Rational& x, const Rational& y); // max #endif friend Rational operator - (const Rational& x); // builtin Rational functions void negate(); // x = -x void invert(); // x = 1/x friend int sign(const Rational& x); // -1, 0, or +1 friend Rational abs(const Rational& x); // absolute value friend Rational sqr(const Rational& x); // square friend Rational pow(const Rational& x, long y); friend Rational pow(const Rational& x, Integer& y); const Integer& numerator() const; const Integer& denominator() const; // coercion & conversion operator double() const; friend Integer floor(const Rational& x); friend Integer ceil(const Rational& x); friend Integer trunc(const Rational& x); friend Integer round(const Rational& x); friend istream& operator >> (istream& s, Rational& y); friend ostream& operator << (ostream& s, const Rational& y); // procedural versions of operators friend int compare(const Rational& x, const Rational& y); friend void add(const Rational& x, const Rational& y, Rational& dest); friend void sub(const Rational& x, const Rational& y, Rational& dest); friend void mul(const Rational& x, const Rational& y, Rational& dest); friend void div(const Rational& x, const Rational& y, Rational& dest); // error detection volatile void error(const char* msg) const; int OK() const; }; typedef Rational RatTmp; // backwards compatibility //#ifdef __OPTIMIZE__ inline Rational::Rational() {} inline Rational::~Rational() {} inline Rational::Rational(const Rational& y) :num(y.num), den(y.den) {} inline Rational::Rational(const Integer& n) :num(n), den(1) {} inline Rational::Rational(const Integer& n, const Integer& d) :num(n),den(d) { normalize(); } inline Rational::Rational(long n, long d) :num(n), den(d) { normalize(); } inline void Rational::operator = (const Rational& y) { num = y.num; den = y.den; } inline int operator == (const Rational& x, const Rational& y) { return compare(x.num, y.num) == 0 && compare(x.den, y.den) == 0; } inline int operator != (const Rational& x, const Rational& y) { return compare(x.num, y.num) != 0 || compare(x.den, y.den) != 0; } inline int operator < (const Rational& x, const Rational& y) { return compare(x, y) < 0; } inline int operator <= (const Rational& x, const Rational& y) { return compare(x, y) <= 0; } inline int operator > (const Rational& x, const Rational& y) { return compare(x, y) > 0; } inline int operator >= (const Rational& x, const Rational& y) { return compare(x, y) >= 0; } inline int sign(const Rational& x) { return sign(x.num); } inline void Rational::negate() { num.negate(); } #ifdef __GNUG__ inline Rational operator ? (const Rational& x, const Rational& y) { if (compare(x, y) >= 0) return x; else return y; } #endif inline Rational operator + (const Rational& x, const Rational& y) return r { add(x, y, r); } inline Rational operator - (const Rational& x, const Rational& y) return r { sub(x, y, r); } inline Rational operator * (const Rational& x, const Rational& y) return r { mul(x, y, r); } inline Rational operator / (const Rational& x, const Rational& y) return r { div(x, y, r); } inline void Rational::operator += (const Rational& y) { add(*this, y, *this); } inline void Rational::operator -= (const Rational& y) { sub(*this, y, *this); } inline void Rational::operator *= (const Rational& y) { mul(*this, y, *this); } inline void Rational::operator /= (const Rational& y) { div(*this, y, *this); } inline const Integer& Rational::numerator() const { return num; } inline const Integer& Rational::denominator() const { return den; } inline Rational::operator double() const { return ratio(num, den); } //#endif #endif onal& y) { add(*thislibg++/g++-include/SFile.h 644 473 0 3651 4677677723 10334 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SFile_h #pragma once #define _SFile_h 1 #include class SFile: public File { protected: int sz; // unit size for structured binary IO public: SFile(); SFile(const char* filename, int size, io_mode m, access_mode a); SFile(const char* filename, int size, const char* m); SFile(int filedesc, int size, io_mode m); SFile(FILE* fileptr, int size); ~SFile(); int size(); int setsize(int s); SFile& get(void* x); SFile& put(void* x); SFile& operator[](long i); }; //#ifdef __OPTIMIZE__ inline int SFile::size() { return sz; } inline int SFile::setsize(int s) { int old = sz; sz = s; return old; } inline SFile& SFile::get(void* x) { read(x, sz, 1); return *this; } inline SFile& SFile::put(void* x) { write(x, sz, 1); return *this; } inline SFile& SFile::operator[](long i) { seek(i * sz, 0); return *this; } //#endif #endif (int s); SFile& get(void* x); SFile& put(void* x); SFile& operator[](lolibg++/g++-include/SampleHistogra 644 473 0 3533 4677677723 12025 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef SampleHistogram_h #pragma once #define SampleHistogram_h 1 #include #include "SampleStatistic.h" extern const int SampleHistogramMinimum; extern const int SampleHistogramMaximum; class SampleHistogram : public SampleStatistic { protected: short howManyBuckets; int *bucketCount; double *bucketLimit; public: SampleHistogram(double low, double hi, double bucketWidth = -1.0); ~SampleHistogram(); virtual void reset(); virtual void operator+=(double); int similarSamples(double); inline int buckets() { return(howManyBuckets); }; inline double bucketThreshold(int i) { if (i < 0 || i >= howManyBuckets) error("invalid bucket access"); return(bucketLimit[i]); } inline int inBucket(int i) { if (i < 0 || i >= howManyBuckets) error("invalid bucket access"); return(bucketCount[i]); } void printBuckets(ostream&); }; #endif eHistogram(); virtual void reset(); virtual void operator+=(double); int similarSamples(double); inline int buckets() { return(howManyBuckets); };libg++/g++-include/SampleStatisti 644 473 0 3445 4677677723 12053 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef SampleStatistic_h #pragma once #define SampleStatistic_h 1 #include class SampleStatistic { protected: int n; double x; double x2; double minValue, maxValue; public : inline SampleStatistic(){ reset();} virtual void reset(); virtual void operator+=(double); inline int samples() {return(n);} double mean(); double stdDev(); double var(); inline double min() {return(minValue);} inline double max() {return(maxValue);} double confidence(int p_percentage); double confidence(double p_value); void error(const char* msg); }; // error handlers extern void default_SampleStatistic_error_handler(const char*); extern one_arg_error_handler_t SampleStatistic_error_handler; extern one_arg_error_handler_t set_SampleStatistic_error_handler(one_arg_error_handler_t f); #endif double stdDev(); double var(); inline double min() {return(minValue);} inline double max() {return(maxValue);} double confidence(int p_percentage); double confidence(double p_value); void libg++/g++-include/String.h 644 473 0 103620 4677677724 10636 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _String_h #pragma once #define _String_h 1 #include struct StrRep // internal String representations { unsigned short len; // string length unsigned short sz; // allocated space char s[1]; // the string starts here // (at least 1 char for trailing null) // allocated & expanded via non-public fcts }; // primitive ops on StrReps -- nearly all String fns go through these. StrRep* Salloc(StrRep*, const char*, int, int); StrRep* Scopy(StrRep*, StrRep*); StrRep* Sresize(StrRep*, int); StrRep* Scat(StrRep*, const char*, int, const char*, int); StrRep* Scat(StrRep*, const char*, int,const char*,int, const char*,int); StrRep* Sprepend(StrRep*, const char*, int); StrRep* Sreverse(StrRep*, StrRep*); StrRep* Supcase(StrRep*, StrRep*); StrRep* Sdowncase(StrRep*, StrRep*); StrRep* Scapitalize(StrRep*, StrRep*); // These classes need to be defined in the order given class String; class SubString; class Regex; struct re_pattern_buffer; // defined elsewhere struct re_registers; class Regex { private: friend class String; friend class SubString; Regex(const Regex&) {} // no X(X&) void operator = (const Regex&) {} // no assignment protected: re_pattern_buffer* buf; re_registers* reg; void initialize(const char* t, int tlen, int fast, int bufsize, const char* transtable); public: Regex(const char* t, int fast = 0, int bufsize = 40, const char* transtable = 0); Regex(const String& x, int fast = 0, int bufsize = 40, const char* transtable = 0); ~Regex(); int match(const char* s, int len, int pos = 0) const; int search(const char* s, int len, int& matchlen, int startpos = 0) const; int match_info(int& start, int& length, int nth = 0) const; int OK() const; // representation invariant }; class SubString { friend class String; protected: String& S; // The String I'm a substring of unsigned short pos; // starting position in S's rep unsigned short len; // length of substring void assign(StrRep*, const char*, int = -1); SubString(String& x, int p, int l); SubString(const SubString& x); public: // Note there are no public constructors. SubStrings are always // created via String operations ~SubString(); void operator = (const String& y); void operator = (const SubString& y); void operator = (const char* t); void operator = (char c); // return 1 if target appears anywhere in SubString; else 0 int contains(char c) const; int contains(const String& y) const; int contains(const SubString& y) const; int contains(const char* t) const; int contains(const Regex& r) const; // return 1 if target matches entire SubString int matches(const Regex& r) const; // IO friend ostream& operator<<(ostream& s, const SubString& x); // status int length() const; int empty() const; const char* chars() const; int OK() const; }; class String { friend class SubString; friend class Regex; protected: StrRep* rep; // Strings are pointers to their representations // some helper functions int search(int, int, const char*, int = -1) const; int search(int, int, char) const; int match(int, int, int, const char*, int = -1) const; int _gsub(const char*, int, const char* ,int); int _gsub(const Regex&, const char*, int); SubString _substr(int, int); public: // constructors & assignment String(); String(const String& x); String(const SubString& x); String(const char* t); String(const char* t, int len); String(char c); ~String(); void operator = (const String& y); void operator = (const char* y); void operator = (char c); void operator = (const SubString& y); // concatenation void operator += (const String& y); void operator += (const SubString& y); void operator += (const char* t); void operator += (char c); void prepend(const String& y); void prepend(const SubString& y); void prepend(const char* t); void prepend(char c); // See below for inline declarations of constructive versions, like // String operator + (const String& x, const String& y); // procedural versions: // concatenate first 2 args, store result in last arg friend void cat(const String&, const String&, String&); friend void cat(const String&, const SubString&, String&); friend void cat(const String&, const char*, String&); friend void cat(const String&, char, String&); friend void cat(const SubString&, const String&, String&); friend void cat(const SubString&, const SubString&, String&); friend void cat(const SubString&, const char*, String&); friend void cat(const SubString&, char, String&); friend void cat(const char*, const String&, String&); friend void cat(const char*, const SubString&, String&); friend void cat(const char*, const char*, String&); friend void cat(const char*, char, String&); // double concatenation, by request. (yes, there are too many versions, // but if one is supported, then the others should be too...) // Concatenate first 3 args, store in last arg friend void cat(const String&,const String&, const String&,String&); friend void cat(const String&,const String&,const SubString&,String&); friend void cat(const String&,const String&, const char*, String&); friend void cat(const String&,const String&, char, String&); friend void cat(const String&,const SubString&,const String&,String&); friend void cat(const String&,const SubString&,const SubString&,String&); friend void cat(const String&,const SubString&, const char*, String&); friend void cat(const String&,const SubString&, char, String&); friend void cat(const String&,const char*, const String&, String&); friend void cat(const String&,const char*, const SubString&, String&); friend void cat(const String&,const char*, const char*, String&); friend void cat(const String&,const char*, char, String&); friend void cat(const char*, const String&, const String&,String&); friend void cat(const char*,const String&,const SubString&,String&); friend void cat(const char*,const String&, const char*, String&); friend void cat(const char*,const String&, char, String&); friend void cat(const char*,const SubString&,const String&,String&); friend void cat(const char*,const SubString&,const SubString&,String&); friend void cat(const char*,const SubString&, const char*, String&); friend void cat(const char*,const SubString&, char, String&); friend void cat(const char*,const char*, const String&, String&); friend void cat(const char*,const char*, const SubString&, String&); friend void cat(const char*,const char*, const char*, String&); friend void cat(const char*,const char*, char, String&); // searching & matching // return position of target in string or -1 for failure int index(char c, int startpos = 0) const; int index(const String& y, int startpos = 0) const; int index(const SubString& y, int startpos = 0) const; int index(const char* t, int startpos = 0) const; int index(const Regex& r, int startpos = 0) const; // return 1 if target appears anyhere in String; else 0 int contains(char c) const; int contains(const String& y) const; int contains(const SubString& y) const; int contains(const char* t) const; int contains(const Regex& r) const; // return 1 if target appears anywhere after position pos // (or before, if pos is negative) in String; else 0 int contains(char c, int pos) const; int contains(const String& y, int pos) const; int contains(const SubString& y, int pos) const; int contains(const char* t, int pos) const; int contains(const Regex& r, int pos) const; // return 1 if target appears at position pos in String; else 0 int matches(char c, int pos = 0) const; int matches(const String& y, int pos = 0) const; int matches(const SubString& y, int pos = 0) const; int matches(const char* t, int pos = 0) const; int matches(const Regex& r, int pos = 0) const; // return number of occurences of target in String int freq(char c) const; int freq(const String& y) const; int freq(const SubString& y) const; int freq(const char* t) const; // SubString extraction // Note that you can't take a substring of a const String, since // this leaves open the possiblility of indirectly modifying the // String through the SubString SubString at(int pos, int len); SubString at(const String& x, int startpos = 0); SubString at(const SubString& x, int startpos = 0); SubString at(const char* t, int startpos = 0); SubString at(char c, int startpos = 0); SubString at(const Regex& r, int startpos = 0); SubString before(int pos); SubString before(const String& x, int startpos = 0); SubString before(const SubString& x, int startpos = 0); SubString before(const char* t, int startpos = 0); SubString before(char c, int startpos = 0); SubString before(const Regex& r, int startpos = 0); SubString through(int pos); SubString through(const String& x, int startpos = 0); SubString through(const SubString& x, int startpos = 0); SubString through(const char* t, int startpos = 0); SubString through(char c, int startpos = 0); SubString through(const Regex& r, int startpos = 0); SubString from(int pos); SubString from(const String& x, int startpos = 0); SubString from(const SubString& x, int startpos = 0); SubString from(const char* t, int startpos = 0); SubString from(char c, int startpos = 0); SubString from(const Regex& r, int startpos = 0); SubString after(int pos); SubString after(const String& x, int startpos = 0); SubString after(const SubString& x, int startpos = 0); SubString after(const char* t, int startpos = 0); SubString after(char c, int startpos = 0); SubString after(const Regex& r, int startpos = 0); // deletion // delete len chars starting at pos void del(int pos, int len); // delete the first occurrence of target after startpos void del(const String& y, int startpos = 0); void del(const SubString& y, int startpos = 0); void del(const char* t, int startpos = 0); void del(char c, int startpos = 0); void del(const Regex& r, int startpos = 0); // global substitution: substitute all occurrences of pat with repl int gsub(const String& pat, const String& repl); int gsub(const SubString& pat, const String& repl); int gsub(const char* pat, const String& repl); int gsub(const char* pat, const char* repl); int gsub(const Regex& pat, const String& repl); // friends & utilities // split string into array res at separators; return number of elements friend int split(const String& x, String res[], int maxn, const String& sep); friend int split(const String& x, String res[], int maxn, const Regex& sep); friend String common_prefix(const String& x, const String& y, int startpos = 0); friend String common_suffix(const String& x, const String& y, int startpos = -1); friend String replicate(char c, int n); friend String replicate(const String& y, int n); friend String join(String src[], int n, const String& sep); // simple builtin transformations friend String reverse(const String& x); friend String upcase(const String& x); friend String downcase(const String& x); friend String capitalize(const String& x); // in-place versions of above void reverse(); void upcase(); void downcase(); void capitalize(); // element extraction char& operator [] (int i); char elem(int i) const; char firstchar() const; char lastchar() const; // conversion operator const char*() const; const char* chars() const; // IO friend ostream& operator<<(ostream& s, const String& x); friend ostream& operator<<(ostream& s, const SubString& x); friend istream& operator>>(istream& s, String& x); friend int readline(istream& s, String& x, char terminator = '\n', int discard_terminator = 1); // status int length() const; int empty() const; // preallocate some space for String void alloc(int newsize); // report current allocation (not length!) int allocation() const; volatile void error(const char* msg) const; int OK() const; }; typedef String StrTmp; // for backward compatibility // other externs int compare(const String& x, const String& y); int compare(const String& x, const SubString& y); int compare(const String& x, const char* y); int compare(const SubString& x, const String& y); int compare(const SubString& x, const SubString& y); int compare(const SubString& x, const char* y); int fcompare(const String& x, const String& y); // ignore case // some built in regular expressions extern const Regex RXwhite; // = "[ \n\t\r\v\f]+" extern const Regex RXint; // = "-?[0-9]+" extern const Regex RXdouble; // = "-?\\(\\([0-9]+\\.[0-9]*\\)\\| // \\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\) // \\([eE][---+]?[0-9]+\\)?" extern const Regex RXalpha; // = "[A-Za-z]+" extern const Regex RXlowercase; // = "[a-z]+" extern const Regex RXuppercase; // = "[A-Z]+" extern const Regex RXalphanum; // = "[0-9A-Za-z]+" extern const Regex RXidentifier; // = "[A-Za-z_][A-Za-z0-9_]*" //#ifdef __OPTIMIZE__ extern StrRep _nilStrRep; extern String _nilString; // status reports, needed before defining other things inline int String::length() const { return rep->len; } inline int String::empty() const { return rep->len == 0; } inline const char* String::chars() const { return &(rep->s[0]); } inline int String::allocation() const { return rep->sz; } inline void String::alloc(int newsize) { rep = Sresize(rep, newsize); } inline int SubString::length() const { return len; } inline int SubString::empty() const { return len == 0; } inline const char* SubString::chars() const { return &(S.rep->s[pos]); } // constructors inline String::String() : rep(&_nilStrRep) {} inline String::String(const String& x) : rep(Scopy(0, x.rep)) {} inline String::String(const char* t) : rep(Salloc(0, t, -1, -1)) {} inline String::String(const char* t, int tlen) : rep(Salloc(0, t, tlen, tlen)) {} inline String::String(const SubString& y) : rep(Salloc(0, y.chars(), y.length(), y.length())) {} inline String::String(char c) : rep(Salloc(0, &c, 1, 1)) {} inline String::~String() { if (rep != &_nilStrRep) delete rep; } inline SubString::SubString(const SubString& x) :S(x.S), pos(x.pos), len(x.len) {} inline SubString::SubString(String& x, int first, int l) :S(x), pos(first), len(l) {} inline SubString::~SubString() {} // assignment inline void String::operator = (const String& y) { rep = Scopy(rep, y.rep); } inline void String::operator=(const char* t) { rep = Salloc(rep, t, -1, -1); } inline void String::operator=(const SubString& y) { rep = Salloc(rep, y.chars(), y.length(), y.length()); } inline void String::operator=(char c) { rep = Salloc(rep, &c, 1, 1); } inline void SubString::operator = (const char* ys) { assign(0, ys); } inline void SubString::operator = (char ch) { assign(0, &ch, 1); } inline void SubString::operator = (const String& y) { assign(y.rep, y.chars(), y.length()); } inline void SubString::operator = (const SubString& y) { assign(y.S.rep, y.chars(), y.length()); } // Zillions of cats... inline void cat(const String& x, const String& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& x, const char* y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); } inline void cat(const String& x, char y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); } inline void cat(const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); } inline void cat(const SubString& x, char y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); } inline void cat(const char* x, const String& y, String& r) { r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); } inline void cat(const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); } inline void cat(const char* x, const char* y, String& r) { r.rep = Scat(r.rep, x, -1, y, -1); } inline void cat(const char* x, char y, String& r) { r.rep = Scat(r.rep, x, -1, &y, 1); } inline void cat(const String& a, const String& x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const String& x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); } inline void cat(const String& a, const String& x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); } inline void cat(const String& a, const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); } inline void cat(const String& a, const SubString& x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); } inline void cat(const String& a, const char* x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); } inline void cat(const String& a, const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); } inline void cat(const String& a, const char* x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1); } inline void cat(const String& a, const char* x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1); } inline void cat(const char* a, const String& x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const String& x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); } inline void cat(const char* a, const String& x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); } inline void cat(const char* a, const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); } inline void cat(const char* a, const SubString& x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); } inline void cat(const char* a, const char* x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); } inline void cat(const char* a, const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); } inline void cat(const char* a, const char* x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y, -1); } inline void cat(const char* a, const char* x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, &y, 1); } // operator versions inline void String::operator +=(const String& y) { cat(*this, y, *this); } inline void String::operator +=(const SubString& y) { cat(*this, y, *this); } inline void String::operator += (const char* y) { cat(*this, y, *this); } inline void String:: operator +=(char y) { cat(*this, y, *this); } // constructive concatenation inline String operator + (const String& x, const String& y) return r; { cat(x, y, r); } inline String operator + (const String& x, const SubString& y) return r; { cat(x, y, r); } inline String operator + (const String& x, const char* y) return r; { cat(x, y, r); } inline String operator + (const String& x, char y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const String& y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const SubString& y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const char* y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, char y) return r; { cat(x, y, r); } inline String operator + (const char* x, const String& y) return r; { cat(x, y, r); } inline String operator + (const char* x, const SubString& y) return r; { cat(x, y, r); } // prepend inline void String::prepend(const String& y) { rep = Sprepend(rep, y.chars(), y.length()); } inline void String::prepend(const char* y) { rep = Sprepend(rep, y, -1); } inline void String::prepend(char y) { rep = Sprepend(rep, &y, 1); } inline void String::prepend(const SubString& y) { rep = Sprepend(rep, y.chars(), y.length()); } // misc transformations inline String reverse(const String& x) return r; { r.rep = Sreverse(x.rep, r.rep); } inline void String::reverse() { rep = Sreverse(rep, rep); } inline String upcase(const String& x) return r; { r.rep = Supcase(x.rep, r.rep); } inline void String::upcase() { rep = Supcase(rep, rep); } inline String downcase(const String& x) return r; { r.rep = Sdowncase(x.rep, r.rep); } inline void String::downcase() { rep = Sdowncase(rep, rep); } inline String capitalize(const String& x) return r; { r.rep = Scapitalize(x.rep, r.rep); } inline void String::capitalize() { rep = Scapitalize(rep, rep); } // element extraction inline char& String::operator [] (int i) { if (((unsigned)i) >= length()) error("invalid index"); return rep->s[i]; } inline char String::elem (int i) const { if (((unsigned)i) >= length()) error("invalid index"); return rep->s[i]; } inline char String::firstchar() const { return elem(0); } inline char String::lastchar() const { return elem(length() - 1); } // searching inline int String::index(char c, int startpos) const { return search(startpos, length(), c); } inline int String::index(const char* t, int startpos) const { return search(startpos, length(), t); } inline int String::index(const String& y, int startpos) const { return search(startpos, length(), y.chars(), y.length()); } inline int String::index(const SubString& y, int startpos) const { return search(startpos, length(), y.chars(), y.length()); } inline int String::index(const Regex& r, int startpos) const { int unused; return r.search(chars(), length(), unused, startpos); } inline int String::contains(char c) const { return search(0, length(), c) >= 0; } inline int String::contains(const char* t) const { return search(0, length(), t) >= 0; } inline int String::contains(const String& y) const { return search(0, length(), y.chars(), y.length()) >= 0; } inline int String::contains(const SubString& y) const { return search(0, length(), y.chars(), y.length()) >= 0; } inline int String::contains(char c, int p) const { return match(p, length(), 0, &c, 1) >= 0; } inline int String::contains(const char* t, int p) const { return match(p, length(), 0, t) >= 0; } inline int String::contains(const String& y, int p) const { return match(p, length(), 0, y.chars(), y.length()) >= 0; } inline int String::contains(const SubString& y, int p) const { return match(p, length(), 0, y.chars(), y.length()) >= 0; } inline int String::contains(const Regex& r) const { int unused; return r.search(chars(), length(), unused, 0) >= 0; } inline int String::contains(const Regex& r, int p) const { return r.match(chars(), length(), p) >= 0; } inline int String::matches(const SubString& y, int p) const { return match(p, length(), 1, y.chars(), y.length()) >= 0; } inline int String::matches(const String& y, int p) const { return match(p, length(), 1, y.chars(), y.length()) >= 0; } inline int String::matches(const char* t, int p) const { return match(p, length(), 1, t) >= 0; } inline int String::matches(char c, int p) const { return match(p, length(), 1, &c, 1) >= 0; } inline int String::matches(const Regex& r, int p) const { int l = (p < 0)? -p : length() - p; return r.match(chars(), length(), p) == l; } inline int SubString::contains(const char* t) const { return S.search(pos, pos+len, t) >= 0; } inline int SubString::contains(const String& y) const { return S.search(pos, pos+len, y.chars(), y.length()) >= 0; } inline int SubString::contains(const SubString& y) const { return S.search(pos, pos+len, y.chars(), y.length()) >= 0; } inline int SubString::contains(char c) const { return S.search(pos, pos+len, 0, c) >= 0; } inline int SubString::contains(const Regex& r) const { int unused; return r.search(chars(), len, unused, 0) >= 0; } inline int SubString::matches(const Regex& r) const { return r.match(chars(), len, 0) == len; } inline int String::gsub(const String& pat, const String& r) { return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); } inline int String::gsub(const SubString& pat, const String& r) { return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); } inline int String::gsub(const Regex& pat, const String& r) { return _gsub(pat, r.chars(), r.length()); } inline int String::gsub(const char* pat, const String& r) { return _gsub(pat, -1, r.chars(), r.length()); } inline int String::gsub(const char* pat, const char* r) { return _gsub(pat, -1, r, -1); } inline String::operator const char*() const { return str(chars()); } inline ostream& operator<<(ostream& s, const String& x) { s.put(x.chars()); return s; } // a zillion comparison operators inline int operator==(const String& x, const String& y) { return compare(x, y) == 0; } inline int operator!=(const String& x, const String& y) { return compare(x, y) != 0; } inline int operator>(const String& x, const String& y) { return compare(x, y) > 0; } inline int operator>=(const String& x, const String& y) { return compare(x, y) >= 0; } inline int operator<(const String& x, const String& y) { return compare(x, y) < 0; } inline int operator<=(const String& x, const String& y) { return compare(x, y) <= 0; } inline int operator==(const String& x, const SubString& y) { return compare(x, y) == 0; } inline int operator!=(const String& x, const SubString& y) { return compare(x, y) != 0; } inline int operator>(const String& x, const SubString& y) { return compare(x, y) > 0; } inline int operator>=(const String& x, const SubString& y) { return compare(x, y) >= 0; } inline int operator<(const String& x, const SubString& y) { return compare(x, y) < 0; } inline int operator<=(const String& x, const SubString& y) { return compare(x, y) <= 0; } inline int operator==(const String& x, const char* t) { return compare(x, t) == 0; } inline int operator!=(const String& x, const char* t) { return compare(x, t) != 0; } inline int operator>(const String& x, const char* t) { return compare(x, t) > 0; } inline int operator>=(const String& x, const char* t) { return compare(x, t) >= 0; } inline int operator<(const String& x, const char* t) { return compare(x, t) < 0; } inline int operator<=(const String& x, const char* t) { return compare(x, t) <= 0; } inline int operator==(const SubString& x, const String& y) { return compare(y, x) == 0; } inline int operator!=(const SubString& x, const String& y) { return compare(y, x) != 0; } inline int operator>(const SubString& x, const String& y) { return compare(y, x) < 0; } inline int operator>=(const SubString& x, const String& y) { return compare(y, x) <= 0; } inline int operator<(const SubString& x, const String& y) { return compare(y, x) > 0; } inline int operator<=(const SubString& x, const String& y) { return compare(y, x) >= 0; } inline int operator==(const SubString& x, const SubString& y) { return compare(x, y) == 0; } inline int operator!=(const SubString& x, const SubString& y) { return compare(x, y) != 0; } inline int operator>(const SubString& x, const SubString& y) { return compare(x, y) > 0; } inline int operator>=(const SubString& x, const SubString& y) { return compare(x, y) >= 0; } inline int operator<(const SubString& x, const SubString& y) { return compare(x, y) < 0; } inline int operator<=(const SubString& x, const SubString& y) { return compare(x, y) <= 0; } inline int operator==(const SubString& x, const char* t) { return compare(x, t) == 0; } inline int operator!=(const SubString& x, const char* t) { return compare(x, t) != 0; } inline int operator>(const SubString& x, const char* t) { return compare(x, t) > 0; } inline int operator>=(const SubString& x, const char* t) { return compare(x, t) >= 0; } inline int operator<(const SubString& x, const char* t) { return compare(x, t) < 0; } inline int operator<=(const SubString& x, const char* t) { return compare(x, t) <= 0; } inline Regex::Regex(const String& x, int fast, int bufsize, const char* transtable) { initialize(x.chars(), x.length(), fast, bufsize, transtable); } inline Regex::Regex(const char* t, int fast, int bufsize, const char* transtable) { initialize(t, -1, fast, bufsize, transtable); } // a helper needed by at, before, etc. inline SubString String::_substr(int first, int l) { if (first < 0 || (unsigned)(first + l) > length()) return SubString(_nilString, 0, 0) ; else return SubString(*this, first, l); } //#endif #endif const char* transtable) { initialize(x.chars(), x.length(), fast, bufsize, transtable); } inlilibg++/g++-include/Uniform.h 644 473 0 3477 4677677724 10760 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Uniform_h #pragma once #define _Uniform_h 1 #include // // The interval [lo..hi] // class Uniform: public Random { double pLow; double pHigh; double delta; public: Uniform(double low, double high, RNG *gen); double low(); double low(double x); double high(); double high(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline Uniform::Uniform(double low, double high, RNG *gen):(gen) { pLow = (low < high) ? low : high; pHigh = (low < high) ? high : low; delta = pHigh - pLow; } inline double Uniform::low() { return pLow; } inline double Uniform::low(double x) { double tmp = pLow; pLow = x; delta = pHigh - pLow; return tmp; } inline double Uniform::high() { return pHigh; } inline double Uniform::high(double x) { double tmp = pHigh; pHigh = x; delta = pHigh - pLow; return tmp; } //#endif #endif line Uniform::Uniform(double low, double high, RNG *gen):(gen) { pLow = (low < high) ? low : high; pHigh = (low < high) ? high : low; delta = pHigh - pLow; } inline double Uniform:libg++/g++-include/Weibull.h 644 473 0 3514 4677677724 10734 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Weibull_h #pragma once #define _Weibull_h #include class Weibull: public Random { protected: double pAlpha; double pInvAlpha; double pBeta; void setState(); public: Weibull(double alpha, double beta, RNG *gen); double alpha(); double alpha(double x); double beta(); double beta(double x); virtual double operator()(); }; //#ifdef __OPTIMIZE__ inline void Weibull::setState() { pInvAlpha = 1.0 / pAlpha; } inline Weibull::Weibull(double alpha, double beta, RNG *gen) : (gen) { pAlpha = alpha; pBeta = beta; setState(); } inline double Weibull::alpha() { return pAlpha; } inline double Weibull::alpha(double x) { double tmp = pAlpha; pAlpha = x; setState(); return tmp; } inline double Weibull::beta() { return pBeta; }; inline double Weibull::beta(double x) { double tmp = pBeta; pBeta = x; return tmp; }; //#endif #endif inline void Weibull::setState() { pInvAlpha = 1.0 / pAlpha; } inline Weibull::Weibull(double alpha, double beta, RNG *gen) : (gen) { pAlpha = alpha; pBeta = beta; selibg++/g++-include/assert.h 644 473 0 3017 4677677724 10630 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* Allow this file to be included multiple times with different settings of NDEBUG. */ #undef assert #undef assertval #ifdef NDEBUG #define assert(ignore) #define assertval(ex) (ex) #else extern "C" void __eprintf (char*, int, char*); /* Defined in gnulib */ extern "C" volatile void abort(); #define assert(ex) \ ((ex) ? 1 : \ (__eprintf("Failed assertion " #ex " at line %d of `%s'.\n", \ __LINE__, __FILE__), abort (), 0)) #define assertval(ex) \ ((ex) ? 1 : \ (__eprintf("Failed assertion " #ex " at line %d of `%s'.\n", \ __LINE__, __FILE__), abort (), 0)) #endif NDEBUG t(ignore) #define assertval(ex) (ex) #else extern "C" void __eprintf (char*, int, char*); /* Defined in gnulib */ extern "C" volatile void abort(); #define assert(ex) \ ((ex) ? 1 : \ (__eprintf("Failed assertion " #ex " at line %d of `%s'.\n", \ __LINE__, __FILE__), abort (), 0)) #define assertval(ex) \ ((ex) ? 1 : \ (__eprintf("Failed assertion " #ex " at line %d of `%s'.\n", \ __LINE__, __FILE__), abort (), 0)) libg++/g++-include/builtin.h 644 473 0 7030 4677677725 10775 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* arithmetic, etc. functions on built in types */ #ifndef _builtin_h #pragma once #define _builtin_h 1 typedef void (*one_arg_error_handler_t)(const char*); typedef void (*two_arg_error_handler_t)(const char*, const char*); #include #include #include long gcd(long, long); long lg(unsigned long); double pow(double, long); long pow(long, long); double start_timer(); double return_elapsed_time(double last_time = 0.0); char* itoa(long x, int base = 10, int width = 0); char* itoa(unsigned long x, int base = 10, int width = 0); #ifdef __GNUG__ char* itoa(long long x, int base = 10, int width = 0); char* itoa(unsigned long long x, int base = 10, int width = 0); #endif char* dtoa(double x, char cvt = 'g', int width = 0, int prec = 6); char* hex(long x, int width = 0); char* hex(unsigned long x, int width = 0); char* oct(long x, int width = 0); char* oct(unsigned long x, int width = 0); char* dec(long x, int width = 0); char* dec(unsigned long x, int width = 0); char* form(const char* fmt ...); char* chr(char ch, int width = 0); char* str(const char* s, int width = 0); unsigned int hashpjw(const char*); unsigned int multiplicativehash(int); unsigned int foldhash(double); extern void default_one_arg_error_handler(const char*); extern void default_two_arg_error_handler(const char*, const char*); extern two_arg_error_handler_t lib_error_handler; extern two_arg_error_handler_t set_lib_error_handler(two_arg_error_handler_t f); //#ifdef __OPTIMIZE__ static inline double abs(double arg) { return (arg < 0.0)? -arg : arg; } static inline float abs(float arg) { return (arg < 0.0)? -arg : arg; } static inline short abs(short arg) { return (arg < 0)? -arg : arg; } static inline long abs(long arg) { return (arg < 0)? -arg : arg; } static inline int sign(long arg) { return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 ); } static inline int sign(double arg) { return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 ); } static inline long sqr(long arg) { return arg * arg; } static inline double sqr(double arg) { return arg * arg; } static inline int even(long arg) { return !(arg & 1); } static inline int odd(long arg) { return (arg & 1); } static inline long lcm(long x, long y) { return x / gcd(x, y) * y; } static inline void setbit(long& x, long b) { x |= (1 << b); } static inline void clearbit(long& x, long b) { x &= ~(1 << b); } static inline int testbit(long x, long b) { return ((x & (1 << b)) != 0); } //#endif #endif ng arg) { return arg * arg; } static inline double sqr(double arg) { return arg * arg; } static inline int even(long arg) { return !(arg & 1); } static inline int odd(long arg) { return (arg & 1); } static inline long lcm(long x, long y) { return x / gcd(x, y) * y; } static inline void setbit(long& x, long b) { x |= (1 << b); } static inline void clearbit(long& x, long b) { x &= ~(1 << b); } static inline int testbit(long x, long b) { return ((x & (1 << b)) != libg++/g++-include/compare.h 644 473 0 3352 4677677725 10760 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _compare_h #pragma once #define _compare_h 1 #include inline int compare(int a, int b) { return a - b; } inline int compare(short a, short b) { return a - b; } inline int compare(char a, char b) { return a - b; } inline int compare(unsigned long a, unsigned long b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(unsigned int a, unsigned int b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(unsigned short a, unsigned short b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(unsigned char a, unsigned char b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(float a, float b) { return a - b; } inline int compare(double a, double b) { return a - b; } inline int compare(const char* a, const char* b) { return strcmp(a,b); } #endif (a > b)? 1 : 0; } inline int compare(unsigned int a, unsigned int b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(unsigned short a, unsigned short b) { return (a < b)? -1 : (a > b)? 1 : 0; } inline int compare(unsigned char a, unsigned char b) { return libg++/g++-include/ctype.h 644 473 0 3624 4677677725 10460 // Here's a ctype.h for SunOS-3 and vax 4.3BSD. // It will probably work on most BSD derived systems. // Just compare it to the C version to verify. // No big deal, but it will save you some typing. #ifndef _ctype_h #pragma once #define _ctype_h #include /* sorry, but needed for USG stuff */ static const int _U = 01; static const int _L = 02; static const int _N = 04; static const int _S = 010; static const int _P = 020; static const int _C = 040; #if defined(USG) || defined(DGUX) static const int _B = 0100; /* different from BSD */ static const int _X = 0200; /* different from BSD */ #else static const int _X = 0100; static const int _B = 0200; #endif #ifdef DGUX #define CTYPE_TYPE short #else #define CTYPE_TYPE char #endif #if defined(DGUX) || defined(USG) || defined(hpux) #define _ctype_ _ctype #endif extern "C" { extern CTYPE_TYPE _ctype_[]; } inline int isalpha(char c) { return ((_ctype_+1)[c]&(_U|_L)); } inline int isupper(char c) { return ((_ctype_+1)[c]&_U); } inline int islower(char c) { return ((_ctype_+1)[c]&_L); } inline int isdigit(char c) { return ((_ctype_+1)[c]&_N); } inline int isxdigit(char c) { return ((_ctype_+1)[c]&_X); } inline int isspace(char c) { return ((_ctype_+1)[c]&_S); } inline int ispunct(char c) { return ((_ctype_+1)[c]&_P); } inline int isalnum(char c) { return ((_ctype_+1)[c]&(_U|_L|_N)); } inline int isprint(char c) { return ((_ctype_+1)[c]&(_P|_U|_L|_N|_B)); } inline int isgraph(char c) { return ((_ctype_+1)[c]&(_P|_U|_L|_N)); } inline int iscntrl(char c) { return ((_ctype_+1)[c]&_C); } inline int isascii(char c) { return ((unsigned)(c)<=0177); } inline int toupper(char c) { return islower(c)? (c-'a'+'A') : c; } inline int tolower(char c) { return isupper(c)? (c-'A'+'a') : c; } inline int toascii(char c) { return ((c)&0177); } #ifdef _ctype_ #undef _ctype_ #endif #ifdef CTYPE_TYPE #undef CTYPE_TYPE #endif #endif _ctype_h ype_+1)[c]&(_P|_U|_L|_N|_B)); } inline int isgraph(char c) { return ((_ctype_+1)[c]&(_P|_U|_L|_N)); } inlinlibg++/g++-include/generic.h 644 473 0 3476 4677677725 10755 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef generic_h #pragma once #define generic_h 1 /* * See the CPP manual, argument prescan section for explanation */ #define name2(a,b) gEnErIc2(a,b) #define gEnErIc2(a,b) a ## b #define name3(a,b,c) gEnErIc3(a,b,c) #define gEnErIc3(a,b,c) a ## b ## c #define name4(a,b,c,d) gEnErIc4(a,b,c,d) #define gEnErIc4(a,b,c,d) a ## b ## c ## d #define GENERIC_STRING(a) gEnErIcStRiNg(a) #define gEnErIcStRiNg(a) #a #define declare(clas,t) name2(clas,declare)(t) #define declare2(clas,t1,t2) name2(clas,declare2)(t1,t2) #define implement(clas,t) name2(clas,implement)(t) #define implement2(clas,t1,t2) name2(clas,implement2)(t1,t2) extern genericerror(int,char*); typedef int (*GPT)(int,char*); #define set_handler(gen,type,x) name4(set_,type,gen,_handler)(x) #define errorhandler(gen,type) name3(type,gen,handler) #define callerror(gen,type,a,b) (*errorhandler(gen,type))(a,b) #endif generic_h iNg(a) #a #define declare(clas,t) name2(clas,declare)(t) #define declare2(clas,t1,t2) name2(clas,declare2)(t1,t2) #define implement(clas,t) name2(clas,implement)(t) #define implelibg++/g++-include/libc.h 644 473 0 71 4677677725 10176 #ifndef _File_h #pragma once #include #endif enericerror(int,char*); typedef int (*GPT)(int,char*); #define set_handler(gen,type,x) name4(set_,type,gen,_handler)(x) #define errorhandler(gen,type) name3(type,gen,handler) #define callerror(gen,type,a,b) (*errorhandler(gen,type))(a,b) #endif generic_h iNg(a) #a #define declare(clas,t) name2(clas,declare)(t) #define declare2(clas,t1,t2) name2(clas,declare2)(t1,t2) #define implement(clas,t) name2(clas,implement)(t) #define implelibg++/g++-include/math.h 644 473 0 11446 4677677725 10306 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _math_h #pragma once #define _math_h 1 #if defined(hp300) && defined(__HAVE_FPU__) #define __HAVE_68881__ 1 #endif #ifdef __HAVE_68881__ /* MC68881/2 Floating-Point Coprocessor */ #include extern "C" { /* fill in what we've left out */ double acosh(double); double asinh(double); double cbrt(double); double copysign(double,double); double erf(double); double erfc(double); double finite(double); double gamma(double); double hypot(double,double); double infnan(int); int isinf(double); int isnan(double); double j0(double); double j1(double); double jn(int, double); double lgamma(double); double y0(double); double y1(double); double yn(int, double); double aint(double); double anint(double); int irint(double); int nint(double); } /* Please add inline asm code for other machines here! */ #else extern "C" { double acos(double); double acosh(double); double asin(double); double asinh(double); double atan(double); double atan2(double, double); double atanh(double); double cbrt(double); double ceil(double); double copysign(double,double); double cos(double); double cosh(double); double drem(double,double); double erf(double); double erfc(double); double exp(double); double expm1(double); double fabs(double); double finite(double); double floor(double); double frexp(double, int*); double gamma(double); double hypot(double,double); double infnan(int); #if !defined(sequent) && !defined(DGUX) /* see below */ int isinf(double); int isnan(double); #endif double j0(double); double j1(double); double jn(int, double); double ldexp(double, int); double lgamma(double); double log(double); double log10(double); double log1p(double); double logb(double); double modf(double, double*); double pow(double, double); double rint(double); double scalb(double, int); double sin(double); double sinh(double); double sqrt(double); double tan(double); double tanh(double); double y0(double); double y1(double); double yn(int, double); double aint(double); double anint(double); int irint(double); int nint(double); } #endif /* libg++ doesn't use this since it is not available on some systems */ /* the following ifdef is just for compiling OOPS */ #ifndef DONT_DECLARE_EXCEPTION struct libm_exception { int type; char* name; double arg1, arg2, retval; }; #define DOMAIN 1 #define SING 2 #define OVERFLOW 3 #define UNDERFLOW 4 #define TLOSS 5 #define PLOSS 6 extern "C" int matherr(libm_exception*); #endif #include /* On some systems, HUGE ought to be MAXFLOAT or IEEE infinity */ #ifndef HUGE #define HUGE MAXDOUBLE #endif /* sequents don't supply these. The following should suffice */ #if defined(sequent) || defined(DGUX) static inline int isnan(double x) { return x != x; } static inline int isinf(double x) { return x > MAXDOUBLE || x < -MAXDOUBLE; } #endif /* These seem to be sun & sysV names of these constants */ #ifndef M_E #define M_E 2.7182818284590452354 #endif #ifndef M_LOG2E #define M_LOG2E 1.4426950408889634074 #endif #ifndef M_LOG10E #define M_LOG10E 0.43429448190325182765 #endif #ifndef M_LN2 #define M_LN2 0.69314718055994530942 #endif #ifndef M_LN10 #define M_LN10 2.30258509299404568402 #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #ifndef M_1_PI #define M_1_PI 0.31830988618379067154 #endif #ifndef M_PI_4 #define M_PI_4 0.78539816339744830962 #endif #ifndef M_2_PI #define M_2_PI 0.63661977236758134308 #endif #ifndef M_2_SQRTPI #define M_2_SQRTPI 1.12837916709551257390 #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 #endif #ifndef PI // as in stroustrup #define PI M_PI #endif #ifndef PI2 #define PI2 M_PI_2 #endif #endif 1_PI #define M_1_PI 0.31830988618379067154 #endif #ifndef M_PI_4 #define M_PI_4 0.78539816339744830962 #endif #ifndef M_2_PI #define M_2_PI 0.63661977236758134308 #endif #ifndef M_2_SQRTPI #define M_2_SQlibg++/g++-include/osfcn.h 644 473 0 144 4677677725 10416 #pragma once #include #include #include #include f #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 #endif #ifndef PI // as in stroustrup #define PI M_PI #endif #ifndef PI2 #define PI2 M_PI_2 #endif #endif 1_PI #define M_1_PI 0.31830988618379067154 #endif #ifndef M_PI_4 #define M_PI_4 0.78539816339744830962 #endif #ifndef M_2_PI #define M_2_PI 0.63661977236758134308 #endif #ifndef M_2_SQRTPI #define M_2_SQlibg++/g++-include/List.hP 644 473 0 15734 4677677726 10415 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _List_h #pragma once #define _List_h 1 #ifndef __typedefs #define __typedefs 1 typedef void (*Procedure)(); typedef (*Mapper)(); typedef (*Combiner)(, ); typedef int (*Predicate)(); typedef int (*Comparator)(, ); #endif #include struct ListNode { ListNode* tl; short ref; hd; }; extern ListNode NilListNode; inline void reference(ListNode* p) { if (p->ref >= 0) ++p->ref; } inline void dereference(ListNode* p) { while (p->ref > 0 && --p->ref == 0) { ListNode* n = p->tl; delete(p); p = n; } } inline ListNode* newListNode( h) { ListNode* p = new ListNode; p->ref = 1; p->hd = h; return p; } inline ListNode* newListNode( h, ListNode* t) { ListNode* p = new ListNode; p->ref = 1; p->hd = h; p->tl = t; return p; } class List { protected: ListNode* P; List(ListNode* p); public: List(); List( head); List( head, List& tl); List(List& a); List(Pix p); ~List(); List& operator = (List& a); int null(); int valid(); operator const void* (); int operator ! (); int length(); int list_length(); & get(); & head(); & operator [] (int n); List nth(int n); List tail(); List last(); List find( targ); List find(List& targ); int contains( targ); int contains(List& targ); int position( targ); friend List copy(List& a); friend List concat(List& a, List& b); friend List append(List& a, List& b); friend List map(Mapper f, List& a); friend List merge(List& a, List& b, Comparator f); friend List combine(Combiner f, List& a, List& b); friend List reverse(List& a); friend List select(Predicate f, List& a); friend List remove( targ, List& a); friend List remove(Predicate f, List& a); friend List subst( old, repl, List& a); void push( x); pop(); void set_tail(List& p); void append(List& p); void prepend(List& p); void del( targ); void del(Predicate f); void select(Predicate f); void subst( old, repl); void reverse(); void sort(Comparator f); void apply(Procedure f); reduce(Combiner f, base); friend int operator == (List& a, List& b); friend int operator != (List& a, List& b); Pix first(); void next(Pix& p); Pix seek( item); & operator () (Pix p); int owns(Pix p); void error(const char*); int OK(); }; inline List::~List() { dereference(P); } inline List::List() { P = &NilListNode; } inline List::List(ListNode* p) { P = p; } inline List::List( head) { P = newListNode(head); P->tl = &NilListNode; } inline List::List( head, List& tl) { P = newListNode(head, tl.P); reference(P->tl); } inline List::List(List& a) { reference(a.P); P = a.P; } inline List& List::operator = (List& a) { reference(a.P); dereference(P); P = a.P; return *this; } inline & List::get() { return P->hd; } inline & List::head() { return P->hd; } inline List List::tail() { reference(P->tl); return List(P->tl); } inline void List::set_tail(List& a) { reference(a.P); dereference(P->tl); P->tl = a.P; } inline int List::null() { return P == &NilListNode; } inline int List::valid() { return P != &NilListNode; } inline List::operator const void* () { return (P == &NilListNode)? 0 : this; } inline int List::operator ! () { return (P == &NilListNode); } inline List List::nth(int n) { for (ListNode* p = P; n-- > 0; p = p->tl); reference(p); return List(p); } inline & List::operator [] (int n) { for (ListNode* p = P; n-- > 0; p = p->tl); return (p->hd); } inline List List::last() { ListNode* p = P; if (p != &NilListNode) while (p->tl != &NilListNode) p = p->tl; reference(p); return List(p); } inline void List::push( head) { ListNode* oldp = P; P = newListNode(head, oldp); } inline List::pop() { res = P->hd; reference(P->tl); dereference(P); P = P->tl; return res; } inline void List::append(List& l) { ListNode* p = P; ListNode* a = l.P; reference(a); if (p != &NilListNode) { while (p->tl != &NilListNode) p = p->tl; p->tl = a; } else P = a; } inline int List::length() { int l = 0; for (ListNode* p = P; p != &NilListNode; p = p->tl) ++l; return l; } inline int operator != (List& x, List& y) { return !(x == y); } inline Pix List::first() { return (P == &NilListNode)? 0 : Pix(P); } inline & List::operator () (Pix p) { return ((ListNode*)p)->hd; } inline void List::next(Pix& p) { if (p != 0) { p = Pix(((ListNode*)p)->tl); if (p == &NilListNode) p = 0; } } inline List::List(Pix p) { P = (ListNode*)p; reference(P); } #endif tNode* p = P; p != &NilListNode; libg++/g++-include/setjmp.h 644 473 0 452 4677677726 10613 #ifndef _setjmp_h #pragma once extern "C" { #define setjmp C_header_setjmp #define longjmp C_header_longjmp #include "/usr/include/setjmp.h" #undef setjmp #undef longjmp #ifndef _setjmp_h #define _setjmp_h 1 #endif extern int setjmp(jmp_buf); extern void longjmp(jmp_buf, int); } #endif if (p != 0) { p = Pix(((ListNode*)p)->tl); if (p == &NilListNode) p = 0; } } inline List::List(Pix p) { P = (ListNode*)p; reference(P); } #endif tNode* p = P; p != &NilListNode; libg++/g++-include/std.h 644 473 0 17703 4677677726 10152 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _std_h #pragma once #define _std_h 1 #include /* sorry, but needed for DGUX folks... */ #include /* sorry, but needed for USG folks... */ extern "C" { void volatile _exit(int); void volatile abort(void); int abs(int); int access(const char*, int); int acct(const char*); unsigned alarm(unsigned); double atof(const char*); int atoi(const char*); long atol(const char*); int bind(int, void*, int); int brk(void*); int bsearch (const void *, const void *, unsigned long, unsigned long, auto int (*ptf)(const void*, const void*)); void* calloc(unsigned, unsigned); void cfree(void*); int chdir(const char*); int chmod(const char*, int); int chown(const char*, int, int); long clock(void); int close(int); #ifdef DGUX int creat(char*, unsigned long int); #else int creat(const char*, unsigned long int); #endif char* crypt(const char*, const char*); char* ctermid(char*); char* cuserid(char*); double drand48(void); int dup(int); int dup2(int, int); int dysize(int); char* ecvt(double, int, int*, int*); char* encrypt(char*, int); double erand(short*); int execl(const char*, const char *, ...); int execle(const char*, const char *, ...); int execlp(const char*, const char*, ...); int exect(const char*, const char**, char**); int execv(const char*, const char**); int execve(const char*, const char**, char**); int execvp(const char*, const char**); void volatile exit(int); int fchmod(int, int); int fchown(int, int, int); int fcntl(int, int, ...); char* fcvt(double, int, int*, int*); int ffs(int); int flock(int, int); int fork(void); void free(void*); int fsync(int); long ftok(const char*, int); int ftruncate(int, unsigned long); char* gcvt(double, int, char*); char* getcwd(char*, int); int getdomainname(char*, int); int getdtablesize(void); int getegid(void); char* getenv(const char*); int geteuid(void); int getgid(void); int getgroups(int, int*); long gethostid(void); int gethostname(char*, int); char* getlogin(void); int getopt(int, const char**, const char*); int getpagesize(void); char* getpass(const char*); int getpgrp(...); int getpid(void); int getppid(void); int getpriority(int, int); int getpw(int, char*); unsigned getuid(void); char* getwd(char*); char* initstate(unsigned, char*, int); int ioctl(int, int, char*); int isatty(int); long jrand48(short*); int kill(int, int); int killpg(int, int); void lcong48(short*); int link(const char*, const char*); int listen(int, int); int lock(int, int, long); long lrand48(void); long lseek(int, long, int); void* malloc(unsigned); unsigned malloc_usable_size(void*); void* memalign(unsigned, unsigned); void* memccpy(void*, const void*, int, int); void* memchr(const void*, int, int); int memcmp(const void*, const void*, int); void* memcpy(void*, const void*, int); void* memset(void*, int, int); int mkdir(const char*, int); int mknod(const char*, int, int); int mkstemp(char*); char* mktemp(char*); long mrand48(void); int nice(int); long nrand48(short*); #ifdef DGUX int open(char*, int, ...); #else int open(const char*, int, ...); #endif void volatile pause(void); void perror(const char*); int pipe(int*); int profil(char*, int, int, int); int psignal(unsigned, char*); int ptrace(int, int, int, int); int putenv(const char*); int qsort(void*, int, unsigned, auto (*ptf)(void*,void*)); int rand(void); long random(void); int read(int, void*, unsigned); int readlink(const char*, char*, int); void* realloc(void*, unsigned); int rename(const char*, const char*); int rmdir(const char*); void* sbrk(int); short* seed48(short*); int send(int, char*, int, int); int setgid(int); int sethostname(char*, int); int setkey(const char*); int setpgrp(...); int setpriority(int, int, int); int setregid(int, int); int setreuid(int, int); char* setstate(char*); int setuid(int); int sigblock(int); int siginterrupt(int, int); int sigpause(int); int sigsetmask(int); unsigned sleep(unsigned); int socket(int, int, int); int srand(int); void srand48(long); void srandom(int); int stime(long*); char* strcat(char*, const char*); char* strchr(const char*, int); int strcmp(const char*, const char*); char* strcpy(char*, const char*); int strcspn(const char*, const char*); char* strdup(const char*); int strlen(const char*); char* strncat(char*, const char*, int); int strncmp(const char*, const char*, int); char* strncpy(char*, const char*, int); char* strpbrk(const char*, const char*); char* strrchr(const char*, int); int strspn(const char*, const char*); double strtod(const char*, char**); char* strtok(char*, const char*); long strtol(const char*, char**, int); void swab(void*, void*, int); int symlink(const char*, const char*); int syscall(int, ...); int system(const char*); char* tempnam(const char*, const char*); int tgetent(char*, char*); int tgetnum(char*); int tgetflag(char*); char* tgetstr(char *, char **); char* tgoto(char*, int, int); long time(long*); char* tmpnam(char*); int tputs(char *, int, auto int (*)()); int truncate(const char*, unsigned long); char* ttyname(int); int ttyslot(void); unsigned ualarm(unsigned, unsigned); long ulimit(int, long); int umask(int); int unlink(const char*); unsigned usleep(unsigned); int vadvise(int); void* valloc(unsigned); int vfork(void); int vhangup(void); int wait(int*); int write(int, const void*, unsigned); } #ifdef USG inline void bzero(void* s, int l) { memset(s, 0, l); } inline void bcopy(const void* s, void* d, int l) { memcpy(d, s, l); } inline int bcmp(const void* s, const void* t, int l) {return memcmp(s,t,l);} inline char* index(const char* s, int c) { return strchr(s, c); } inline char* rindex(const char* s, int c) { return strrchr(s, c); } #else extern "C" { int bcmp(const void*, const void*, int); void bcopy(const void*, void*, int); void bzero(void*, int); char* index(const char*, int); char* rindex(const char*, int); } #endif extern char** environ; extern volatile int errno; extern char* sys_errlist[]; extern int sys_nerr; extern char* optarg; extern int opterr; extern int optind; extern "C" void* alloca(unsigned long); #ifndef alloca #define alloca(x) __builtin_alloca(x) #endif #ifndef __GNUG__ extern "C" void *__builtin_alloca (int); #endif #endif onst void*, void*, int); void bzero(void*, int); char* libg++/g++-include/stdarg.h 644 473 0 3627 4677677726 10624 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _stdarg_h #pragma once #define _stdarg_h 1 #ifndef __GNUG__ extern "C" __builtin_saveregs (); #endif typedef char *va_list; /* Amount of space required in an argument list for an arg of type TYPE. TYPE may alternatively be an expression whose type is used. */ #define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #if defined(sparc) # define va_start(AP, LASTARG) \ (__builtin_saveregs (), AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) #elif defined(mips) # define va_start(AP,LASTARG) {\ static char __vd_alist[16] = "__%%VARARGS"; /* Identify to codegen */\ __builtin_saveregs();\ (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)));} #else # define va_start(AP, LASTARG) \ (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) #endif void va_end (va_list); /* Defined in gnulib */ #define va_end(AP) #define va_arg(AP, TYPE) \ (AP += __va_rounded_size (TYPE), \ *((TYPE *) (AP - __va_rounded_size (TYPE)))) #endif s) # define va_start(AP,LASTARG) {\ static char __vd_alist[16] = "__%%VARARGS"; /* Identify to clibg++/g++-include/stddef.h 644 473 0 2332 4677677726 10601 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _stddef_h #pragma once #define _stddef_h // TRUE, FALSE, bool, are now in , for ANSI compatibility typedef unsigned long size_t; typedef long int ptrdiff_t; #ifdef DGUX typedef int wchar_t; #else typedef unsigned short wchar_t; #endif #ifndef NULL #define NULL 0 #endif #endif along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _stddef_h #pragma once #define _stddef_h // TRUE, FALSE, bool, are now in _file] #define _bufsiz(p) (_bufend(p) - (p)->_base) #ifndef BUFEND_ENTRY_TYPE #define BUFEND_ENTRY_TYPE char * #endif extern "C" { BUFEND_ENTRY_TYPE _bufendtab[]; } #endif /* check this -- hardly any systems need this these days */ /* #define SPRINTF_RETURNS_INT */ /* check and possibly redefine the following */ #define BUFSIZ 1024 extern struct _iobuf { int _cnt; char* _ptr; char* _base; IOBUF_BUFSIZ_FIELD IOBUF_FLAG_TYPE _flag; IOBUF_FILE_TYPE _file; IOBUF_EXTRA_FIELDS } _iob[]; typedef struct _iobuf FILE; #define _IOFBF 00000 #define _IOREAD 00001 #define _IOWRT 00002 #define _IONBF 00004 #define _IOMYBUF 00010 #define _IOEOF 00020 #define _IOERR 00040 #if defined(USG) && !defined(hpux) #define _IOSTRG 00000 /* faked out for USG */ #define _IOLBF 00100 #define _IORW 00200 #define _IOAPPEND 00000 /* faked out for USG */ #elif defined(hpux) #define _IOSTRG 00000 /* faked out for USG */ #define _IOLBF 00200 #define _IORW 00400 #define _IOAPPEND 00000 /* faked out for USG */ #else #define _IOSTRG 00100 #define _IOLBF 00200 #define _IORW 00400 #define _IOAPPEND 01000 #endif #ifdef DGUX #define _IOPBF 00400 /* Boolean - ungetc() not called since fill/flush */ #endif #define EOF (-1) #ifndef NULL #define NULL 0 #endif #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2]) #define getc(p) (--(p)->_cnt>=0?(int)(*(unsigned char*)(p)->_ptr++):_filbuf(p)) #define putc(x,p) (--(p)->_cnt>=0? ((int)((unsigned char)((*(p)->_ptr++=(unsigned)(x))))):_flsbuf((unsigned)(x),p)) #define clearerr(p) ((p)->_flag &= ~(_IOERR|_IOEOF)) #define getchar() getc(stdin) #define putchar(x) putc(x,stdout) #define feof(p) (((p)->_flag&_IOEOF)!=0) #define ferror(p) (((p)->_flag&_IOERR)!=0) #define fileno(p) ((p)->_file) extern "C" { int _doprnt(const char*, void*, FILE*); int _doscan(FILE*, const char*, ...); int _filbuf(FILE*); int _flsbuf(unsigned, FILE*); int fclose(FILE*); FILE* fdopen(int, const char*); int fflush(FILE*); int fgetc(FILE*); char* fgets(char*, int, FILE *); FILE* fopen(const char*, const char*); int fprintf(FILE*, const char* ...); int fputc(int, FILE*); int fputs(const char*, FILE*); int fread(void*, int, int, FILE*); FILE* freopen(const char*, const char*, FILE*); int fscanf(FILE*, const char* ...); int fseek(FILE*, long, int); long ftell(FILE *); int fwrite(const void*, int, int, FILE*); char* gets(char*); int getw(FILE*); int pclose(FILE*); FILE* popen(const char*, const char*); int printf(const char* ...); int puts(const char*); int putw(int, FILE*); int rewind(FILE*); int scanf(const char* ...); int setbuf(FILE*, char*); int setbuffer(FILE*, char*, int); int setlinebuf(FILE*); int setvbuf(FILE*, char*, int, int); int sscanf(char*, const char* ...); FILE* tmpfile(); int ungetc(int, FILE*); int vfprintf(FILE*, const char*, ...); // Third arg to vprintf must be '...' for some machines, & doesn't // hurt for others. int vprintf(const char*, ... ); #ifdef SPRINTF_RETURNS_INT int sprintf(char*, const char* ...); int vsprintf(char*, const char*, ...); #else char* sprintf(char*, const char* ...); char* vsprintf(char*, const char*, ...); #endif } #ifndef L_ctermid #define L_ctermid 9 #endif #ifndef L_cuserid #define L_cuserid 9 #endif #ifndef P_tmpdir #define P_tmpdir "/tmp/" #endif #ifndef L_tmpnam #define L_tmpnam (sizeof(P_tmpdir) + 15) #endif #endif // FILE achines, & doesn't // hurt for others. int vprintf(const char*, ... ); #ifdef SPRINTF_RETURNS_INT int sprintf(char*, const char* ...); int vsprintf(char*, const char*, ...); #else char* sprintf(char*, const char* ...); char* vsprintf(char*, const char*, ...libg++/g++-include/AVec.hP 644 473 0 7023 4677677727 10271 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _AVec_h #pragma once #define _AVec_h 1 #include ".Vec.h" class AVec : public Vec { protected: void check_len(int l); * vec(); AVec(int l, * d); public: AVec (); AVec (int l); AVec (int l, fill_value); AVec (AVec&); ~AVec (); AVec& operator = (AVec& a); AVec& operator = ( fill_value); // vector by scalar -> vector operations friend AVec operator + (AVec& a, b); friend AVec operator - (AVec& a, b); friend AVec operator * (AVec& a, b); friend AVec operator / (AVec& a, b); AVec& operator += ( b); AVec& operator -= ( b); AVec& operator *= ( b); AVec& operator /= ( b); // vector by vector -> vector operations friend AVec operator + (AVec& a, AVec& b); friend AVec operator - (AVec& a, AVec& b); AVec& operator += (AVec& b); AVec& operator -= (AVec& b); AVec operator - (); friend AVec product(AVec& a, AVec& b); AVec& product(AVec& b); friend AVec quotient(AVec& a, AVec& b); AVec& quotient(AVec& b); // vector -> scalar operations friend operator * (AVec& a, AVec& b); sum(); min(); max(); sumsq(); // indexing int min_index(); int max_index(); // redundant but necesssary friend AVec concat(AVec& a, AVec& b); friend AVec map(Mapper f, AVec& a); friend AVec merge(AVec& a, AVec& b, Comparator f); friend AVec combine(Combiner f, AVec& a, AVec& b); friend AVec reverse(AVec& a); AVec at(int from = 0, int n = -1); }; inline AVec::AVec() {} inline AVec::AVec(int l) :(l) {} inline AVec::AVec(int l, fill_value) : (l, fill_value) {} inline AVec::AVec(AVec& v) :(v) {} inline AVec::~AVec() {} inline * AVec::vec() { return s; } inline AVec::AVec(int l, * d) { len = l; s = d; } inline void AVec::check_len(int l) { if (l != len) error("nonconformant vectors."); } #endif reverse(AVec& a); AVec at(int from = 0, int n = -1); }; inline AVec::AVec() {} inline AVec::AVec(int l) :(l) {} inline AVec::AVec(int l, fill_value) : (l, fill_value) {} inline AVec::AVec(AVec& v) :(v) {} inline AVec::~AVec() {} inline * AVec::vec() { return s; } inline AVec::AVec(int l, * d) { len = l; s = d; } inline void AVec::check_len(int l) { if (l != len) error("nonconformant vectlibg++/g++-include/stream.h 644 473 0 237 4677677727 10606 /* ostream.h and istream.h now separately includable */ #ifndef _stream_h #pragma once #define _stream_h 1 #include #include #endif int l) :(l) {} inline AVec::AVec(int l, fill_value) : (l, fill_value) {} inline AVec::AVec(AVec& v) :(v) {} inline AVec::~AVec() {} inline * AVec::vec() { return s; } inline AVec::AVec(int l, * d) { len = l; s = d; } inline void AVec::check_len(int l) { if (l != len) error("nonconformant vectlibg++/g++-include/string.h 644 473 0 21 4677677727 10570 #include istream.h now separately includable */ #ifndef _stream_h #pragma once #define _stream_h 1 #include #include #endif int l) :(l) {} inline AVec::AVec(int l, fill_value) : (l, fill_value) {} inline AVec::AVec(AVec& v) :(v) {} inline AVec::~AVec() {} inline * AVec::vec() { return s; } inline AVec::AVec(int l, * d) { len = l; s = d; } inline void AVec::check_len(int l) { if (l != len) error("nonconformant vectlibg++/g++-include/curses.h 644 473 0 15621 4677677730 10654 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Eric Newton (newton@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* * Edited for compatablity with C++, 2/28/89 * This file has all the /usr/include/curses.h info (with proper prototypes) * used for the CursesWindow classes. You may need to change this to be * compatable with your curses implementation. * */ #ifndef _curses_h #pragma once #define _curses_h # include # include # include extern "C" { # include // protection against possibility that these are macros: #ifndef stty extern int stty(int, struct sgttyb*); #endif #ifndef gtty extern int gtty(int, struct sgttyb*); #endif } typedef char cbool; // curses explicitly declares bools as chars #if defined(hpux) enum CursesStatus { ERR = -1, OK = 0 }; // curses lib uses define's #else enum CursesStatus { ERR = 0, OK = 1 }; // curses lib uses define's #endif /* * BSD'ish. Warning!! * */ # define _ENDLINE 001 # define _FULLWIN 002 # define _SCROLLWIN 004 # define _FLUSH 010 # define _FULLLINE 020 # define _IDLINE 040 # define _STANDOUT 0200 # define _NOCHANGE -1 # define _puts(s) tputs(s, 0, _putchar) /* * Capabilities from termcap */ extern cbool AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL, XB, XN, XT, XS, XX; extern char *AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL, *DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6, *K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL, *KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *SE, *SF, *SO, *SR, *TA, *TE, *TI, *UC, *UE, *UP, *US, *VB, *VS, *VE, *AL_PARM, *DL_PARM, *UP_PARM, *DOWN_PARM, *LEFT_PARM, *RIGHT_PARM; extern char PC; extern cbool GT, NONL, UPPERCASE, normtty, _pfast; struct _win_st { short _cury, _curx; short _maxy, _maxx; short _begy, _begx; short _flags; short _ch_off; cbool _clear; cbool _leave; cbool _scroll; char **_y; short *_firstch; short *_lastch; struct _win_st *_nextp, *_orig; }; #define WINDOW struct _win_st extern cbool My_term; extern cbool _echoit; extern cbool _rawmode; extern cbool _endwin; extern char *Def_term; extern char ttytype[]; extern int LINES; extern int COLS; extern int _tty_ch; extern int _res_flg; typedef struct sgttyb SGTTY; extern SGTTY _tty; /* * standard curses functions. * */ extern "C" { WINDOW * stdscr; WINDOW * curscr; WINDOW * newwin(int lines, int cols, int sy, int sx); WINDOW * subwin(WINDOW *w, int lines, int cols, int sy, int sx); WINDOW * initscr(); int box (WINDOW*, char, char); int delwin(WINDOW*); int mvcur(int, int, int, int); int overlay(WINDOW*, WINDOW*); int overwrite(WINDOW*, WINDOW*); int scroll(WINDOW*); int touchline(WINDOW*, int, int, int); #ifndef DGUX int touchoverlap(WINDOW*, WINDOW*); #endif int touchwin(WINDOW*); int waddch(WINDOW*, char); int waddstr(WINDOW*, const char*); int wclear(WINDOW*); int wclrtobot(WINDOW*); int wclrtoeol(WINDOW*); int wdelch(WINDOW*); int wdeleteln(WINDOW*); int werase(WINDOW*); int wgetch(WINDOW*); int wgetstr(WINDOW*, char*); int winch(WINDOW*); int winsch(WINDOW*, char); int winsertln(WINDOW*); int wmove(WINDOW*, int, int); int wrefresh(WINDOW*); int wstandend(WINDOW*); int wstandout(WINDOW*); int wprintw(WINDOW*, const char * fmt, ...); int mvwprintw(WINDOW*, int y, int x, const char * fmt, ...); int wscanw(WINDOW*, const char *, ...); int mvwscanw(int, int, WINDOW*, const char*, ...); int endwin(); } /* Pseudo functions */ /* * these are inlines rather than defines here so as to allow overloaded * versions in the CursesWindow class */ inline int clearok(WINDOW* win, cbool bf) { return(win->_clear = bf); } inline int leaveok(WINDOW* win, cbool bf) { return(win->_leave = bf); } inline int scrollok(WINDOW* win, cbool bf) { return(win->_scroll = bf); } inline int flushok(WINDOW* win, cbool bf) { return(bf ? (win->_flags |= _FLUSH):(win->_flags &= ~_FLUSH)); } inline void getyx(WINDOW* win, int& y, int& x) { y = win->_cury; x = win->_curx; } inline int winch(WINDOW* win) {return win->_y[win->_cury][win->_curx] & 0177; } #ifdef USG extern "C" { int raw(); int noraw(); int cbreak(); int nocbreak(); } #else inline int raw() { return _tty.sg_flags|=RAW, _pfast=_rawmode=1, stty(_tty_ch,&_tty); } inline int noraw() { return _tty.sg_flags&=~RAW,_rawmode=0,_pfast=!(_tty.sg_flags&CRMOD),stty(_tty_ch,&_tty); } inline int cbreak() { return _tty.sg_flags |= CBREAK, _rawmode = 1, stty(_tty_ch,&_tty); } inline int nocbreak() { return _tty.sg_flags &= ~CBREAK,_rawmode=0,stty(_tty_ch,&_tty); } #endif inline int crmode() { return cbreak(); } inline int nocrmode() { return nocbreak(); } #ifdef USG extern "C" { int _setecho(int); int _setnonl(int); } inline int echo() { return _setecho(1); } inline int noecho() { return _setecho(0); } inline int nl() { return _setnonl(0); } inline int nonl() { return _setnonl(1); } extern "C" { int savetty(); int resetty(); int erasechar(); int killchar(); int baudrate(); } #else inline int echo() { return _tty.sg_flags |= ECHO, _echoit = 1, stty(_tty_ch, &_tty); } inline int noecho() { return _tty.sg_flags &= ~ECHO, _echoit = 0, stty(_tty_ch, &_tty); } inline int nl() { return _tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty); } inline int nonl() { return _tty.sg_flags &= ~CRMOD, _pfast = 1, stty(_tty_ch, &_tty); } inline int savetty() { return (void) gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags; } inline int resetty() { return _tty.sg_flags = _res_flg, stty(_tty_ch, &_tty); } inline int erasechar() { return _tty.sg_erase; } inline int killchar() { return _tty.sg_kill; } inline int baudrate() { return _tty.sg_ospeed; } #endif extern "C" { char *longname(char *, char *); char *getcap(char *); extern char *_unctrl[]; } inline char * unctrl(int c) { return _unctrl[(c) & 0177]; } #endif ty(_tty_ch, &_tty); } inline int savetty() { return (void) gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags; } ilibg++/g++-include/AVLMap.hP 644 473 0 6402 4677677730 10525 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _AVLMap_h #pragma once #define _AVLMap_h 1 #include "..Map.h" struct AVLNode { AVLNode* lt; AVLNode* rt; item; cont; char stat; AVLNode( h, c, AVLNode* l=0, AVLNode* r=0); ~AVLNode(); }; inline AVLNode::AVLNode( h, c, AVLNode* l=0, AVLNode* r=0) :item(h), cont(c), lt(l), rt(r) { stat = 0; } inline AVLNode::~AVLNode() {} typedef AVLNode* AVLNodePtr; class AVLMap : public Map { protected: AVLNode* root; AVLNode* leftmost(); AVLNode* rightmost(); AVLNode* pred(AVLNode* t); AVLNode* succ(AVLNode* t); void _kill(AVLNode* t); void _add(AVLNode*& t); void _del(AVLNode* p, AVLNode*& t); public: AVLMap( dflt); AVLMap(AVLMap& a); ~AVLMap(); & operator [] ( key); void del( key); Pix first(); void next(Pix& i); & key(Pix i); & contents(Pix i); Pix seek( key); int contains( key); void clear(); Pix last(); void prev(Pix& i); int OK(); }; inline AVLMap::~AVLMap() { _kill(root); } inline AVLMap::AVLMap( dflt) :(dflt) { root = 0; } inline Pix AVLMap::first() { return Pix(leftmost()); } inline Pix AVLMap::last() { return Pix(rightmost()); } inline void AVLMap::next(Pix& i) { if (i != 0) i = Pix(succ((AVLNode*)i)); } inline void AVLMap::prev(Pix& i) { if (i != 0) i = Pix(pred((AVLNode*)i)); } inline & AVLMap::key(Pix i) { if (i == 0) error("null Pix"); return ((AVLNode*)i)->item; } inline & AVLMap::contents(Pix i) { if (i == 0) error("null Pix"); return ((AVLNode*)i)->cont; } inline void AVLMap::clear() { _kill(root); count = 0; root = 0; } inline int AVLMap::contains( key) { return seek(key) != 0; } #endif x(succ((AVLNode*)i)); } inline void AVLMap::prev(Pix& i) { if (i != 0) i = Pix(pred((AVLNode*)i)); } inline & AVLMap::key(Pix i) { if (i == 0) error("null Pix"); return ((AVLNode*)i)->item; } inline & AVlibg++/g++-include/AVLMap.ccP 644 473 0 31173 4677677730 10706 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include "..AVLMap.h" /* constants & inlines for maintaining balance & thread status in tree nodes */ #define AVLBALANCEMASK 3 #define AVLBALANCED 0 #define AVLLEFTHEAVY 1 #define AVLRIGHTHEAVY 2 #define LTHREADBIT 4 #define RTHREADBIT 8 static inline int bf(AVLNode* t) { return t->stat & AVLBALANCEMASK; } static inline void set_bf(AVLNode* t, int b) { t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); } static inline int rthread(AVLNode* t) { return t->stat & RTHREADBIT; } static inline void set_rthread(AVLNode* t, int b) { if (b) t->stat |= RTHREADBIT; else t->stat &= ~RTHREADBIT; } static inline int lthread(AVLNode* t) { return t->stat & LTHREADBIT; } static inline void set_lthread(AVLNode* t, int b) { if (b) t->stat |= LTHREADBIT; else t->stat &= ~LTHREADBIT; } /* traversal primitives */ AVLNode* AVLMap::leftmost() { AVLNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } AVLNode* AVLMap::rightmost() { AVLNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } AVLNode* AVLMap::succ(AVLNode* t) { AVLNode* r = t->rt; if (!rthread(t)) while (!lthread(r)) r = r->lt; return r; } AVLNode* AVLMap::pred(AVLNode* t) { AVLNode* l = t->lt; if (!lthread(t)) while (!rthread(l)) l = l->rt; return l; } Pix AVLMap::seek( key) { AVLNode* t = root; if (t == 0) return 0; for (;;) { int cmp = CMP(key, t->item); if (cmp == 0) return Pix(t); else if (cmp < 0) { if (lthread(t)) return 0; else t = t->lt; } else if (rthread(t)) return 0; else t = t->rt; } } /* The combination of threads and AVL bits make adding & deleting interesting, but very awkward. We use the following statics to avoid passing them around recursively */ static int _need_rebalancing; // to send back balance info from rec. calls static * _target_item; // add/del_item target static AVLNode* _found_node; // returned added/deleted node static int _already_found; // for deletion subcases void AVLMap:: _add(AVLNode*& t) { int cmp = CMP(*_target_item, t->item); if (cmp == 0) { _found_node = t; return; } else if (cmp < 0) { if (lthread(t)) { ++count; _found_node = new AVLNode(*_target_item, def); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t->lt; _found_node->rt = t; t->lt = _found_node; set_lthread(t, 0); _need_rebalancing = 1; } else _add(t->lt); if (_need_rebalancing) { switch(bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); return; case AVLLEFTHEAVY: AVLNode* l = t->lt; if (bf(l) == AVLLEFTHEAVY) { if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; } else { AVLNode* r = l->rt; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; return; } } } } else { if (rthread(t)) { ++count; _found_node = new AVLNode(*_target_item, def); set_rthread(t, 0); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t; _found_node->rt = t->rt; t->rt = _found_node; _need_rebalancing = 1; } else _add(t->rt); if (_need_rebalancing) { switch(bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); return; case AVLRIGHTHEAVY: AVLNode* r = t->rt; if (bf(r) == AVLRIGHTHEAVY) { if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; } else { AVLNode* l = r->lt; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; return; } } } } } & AVLMap::operator [] ( item) { if (root == 0) { ++count; root = new AVLNode(item, def); set_rthread(root, 1); set_lthread(root, 1); return root->cont; } else { _target_item = &item; _need_rebalancing = 0; _add(root); return _found_node->cont; } } void AVLMap::_del(AVLNode* par, AVLNode*& t) { int comp; if (_already_found) { if (rthread(t)) comp = 0; else comp = 1; } else comp = CMP(*_target_item, t->item); if (comp == 0) { if (lthread(t) && rthread(t)) { _found_node = t; if (t == par->lt) { set_lthread(par, 1); par->lt = t->lt; } else { set_rthread(par, 1); par->rt = t->rt; } _need_rebalancing = 1; return; } else if (lthread(t)) { _found_node = t; AVLNode* s = succ(t); if (s != 0 && lthread(s)) s->lt = t->lt; t = t->rt; _need_rebalancing = 1; return; } else if (rthread(t)) { _found_node = t; AVLNode* p = pred(t); if (p != 0 && rthread(p)) p->rt = t->rt; t = t->lt; _need_rebalancing = 1; return; } else // replace item & find someone deletable { AVLNode* p = pred(t); t->item = p->item; t->cont = p->cont; _already_found = 1; comp = -1; // fall through below to left } } if (comp < 0) { if (lthread(t)) return; _del(t, t->lt); if (!_need_rebalancing) return; switch (bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); _need_rebalancing = 0; return; case AVLRIGHTHEAVY: AVLNode* r = t->rt; switch (bf(r)) { case AVLBALANCED: if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLRIGHTHEAVY); set_bf(r, AVLLEFTHEAVY); _need_rebalancing = 0; t = r; return; case AVLRIGHTHEAVY: if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; case AVLLEFTHEAVY: AVLNode* l = r->lt; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; } } } else { if (rthread(t)) return; _del(t, t->rt); if (!_need_rebalancing) return; switch (bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); _need_rebalancing = 0; return; case AVLLEFTHEAVY: AVLNode* l = t->lt; switch (bf(l)) { case AVLBALANCED: if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLLEFTHEAVY); set_bf(l, AVLRIGHTHEAVY); _need_rebalancing = 0; t = l; return; case AVLLEFTHEAVY: if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; case AVLRIGHTHEAVY: AVLNode* r = l->rt; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; } } } } void AVLMap::del( item) { if (root == 0) return; _need_rebalancing = 0; _already_found = 0; _found_node = 0; _target_item = &item; _del(root, root); if (_found_node) { delete(_found_node); if (--count == 0) root = 0; } } void AVLMap::_kill(AVLNode* t) { if (t != 0) { if (!lthread(t)) _kill(t->lt); if (!rthread(t)) _kill(t->rt); delete t; } } AVLMap::AVLMap(AVLMap& b) :(b.def) { root = 0; count = 0; for (Pix i = b.first(); i != 0; b.next(i)) (*this)[b.key(i)] = b.contents(i); } int AVLMap::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; AVLNode* trail = leftmost(); AVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } VLMap& b) :(b.def) { root = 0; count = 0; for (Pix i = b.first(); i != 0; b.next(i)) (*this)[b.key(i)] = b.contents(i); } int AVLMap::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; AVLNode* trail = leftmost(); AVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) #include #include ".AVLSet.h" /* constants & inlines for maintaining balance & thread status in tree nodes */ #define AVLBALANCEMASK 3 #define AVLBALANCED 0 #define AVLLEFTHEAVY 1 #define AVLRIGHTHEAVY 2 #define LTHREADBIT 4 #define RTHREADBIT 8 static inline int bf(AVLNode* t) { return t->stat & AVLBALANCEMASK; } static inline void set_bf(AVLNode* t, int b) { t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); } static inline int rthread(AVLNode* t) { return t->stat & RTHREADBIT; } static inline void set_rthread(AVLNode* t, int b) { if (b) t->stat |= RTHREADBIT; else t->stat &= ~RTHREADBIT; } static inline int lthread(AVLNode* t) { return t->stat & LTHREADBIT; } static inline void set_lthread(AVLNode* t, int b) { if (b) t->stat |= LTHREADBIT; else t->stat &= ~LTHREADBIT; } /* traversal primitives */ AVLNode* AVLSet::leftmost() { AVLNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } AVLNode* AVLSet::rightmost() { AVLNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } AVLNode* AVLSet::succ(AVLNode* t) { AVLNode* r = t->rt; if (!rthread(t)) while (!lthread(r)) r = r->lt; return r; } AVLNode* AVLSet::pred(AVLNode* t) { AVLNode* l = t->lt; if (!lthread(t)) while (!rthread(l)) l = l->rt; return l; } Pix AVLSet::seek( key) { AVLNode* t = root; if (t == 0) return 0; for (;;) { int cmp = CMP(key, t->item); if (cmp == 0) return Pix(t); else if (cmp < 0) { if (lthread(t)) return 0; else t = t->lt; } else if (rthread(t)) return 0; else t = t->rt; } } /* The combination of threads and AVL bits make adding & deleting interesting, but very awkward. We use the following statics to avoid passing them around recursively */ static int _need_rebalancing; // to send back balance info from rec. calls static * _target_item; // add/del_item target static AVLNode* _found_node; // returned added/deleted node static int _already_found; // for deletion subcases static AVLNode** _hold_nodes; // used for rebuilding trees static int _max_hold_index; // # elements-1 in _hold_nodes void AVLSet:: _add(AVLNode*& t) { int cmp = CMP(*_target_item, t->item); if (cmp == 0) { _found_node = t; return; } else if (cmp < 0) { if (lthread(t)) { ++count; _found_node = new AVLNode(*_target_item); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t->lt; _found_node->rt = t; t->lt = _found_node; set_lthread(t, 0); _need_rebalancing = 1; } else _add(t->lt); if (_need_rebalancing) { switch(bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); return; case AVLLEFTHEAVY: AVLNode* l = t->lt; if (bf(l) == AVLLEFTHEAVY) { if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; } else { AVLNode* r = l->rt; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; return; } } } } else { if (rthread(t)) { ++count; _found_node = new AVLNode(*_target_item); set_rthread(t, 0); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t; _found_node->rt = t->rt; t->rt = _found_node; _need_rebalancing = 1; } else _add(t->rt); if (_need_rebalancing) { switch(bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); return; case AVLRIGHTHEAVY: AVLNode* r = t->rt; if (bf(r) == AVLRIGHTHEAVY) { if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; } else { AVLNode* l = r->lt; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; return; } } } } } Pix AVLSet::add( item) { if (root == 0) { ++count; root = new AVLNode(item); set_rthread(root, 1); set_lthread(root, 1); return Pix(root); } else { _target_item = &item; _need_rebalancing = 0; _add(root); return Pix(_found_node); } } void AVLSet::_del(AVLNode* par, AVLNode*& t) { int comp; if (_already_found) { if (rthread(t)) comp = 0; else comp = 1; } else comp = CMP(*_target_item, t->item); if (comp == 0) { if (lthread(t) && rthread(t)) { _found_node = t; if (t == par->lt) { set_lthread(par, 1); par->lt = t->lt; } else { set_rthread(par, 1); par->rt = t->rt; } _need_rebalancing = 1; return; } else if (lthread(t)) { _found_node = t; AVLNode* s = succ(t); if (s != 0 && lthread(s)) s->lt = t->lt; t = t->rt; _need_rebalancing = 1; return; } else if (rthread(t)) { _found_node = t; AVLNode* p = pred(t); if (p != 0 && rthread(p)) p->rt = t->rt; t = t->lt; _need_rebalancing = 1; return; } else // replace item & find someone deletable { AVLNode* p = pred(t); t->item = p->item; _already_found = 1; comp = -1; // fall through below to left } } if (comp < 0) { if (lthread(t)) return; _del(t, t->lt); if (!_need_rebalancing) return; switch (bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); _need_rebalancing = 0; return; case AVLRIGHTHEAVY: AVLNode* r = t->rt; switch (bf(r)) { case AVLBALANCED: if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLRIGHTHEAVY); set_bf(r, AVLLEFTHEAVY); _need_rebalancing = 0; t = r; return; case AVLRIGHTHEAVY: if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; case AVLLEFTHEAVY: AVLNode* l = r->lt; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; } } } else { if (rthread(t)) return; _del(t, t->rt); if (!_need_rebalancing) return; switch (bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); _need_rebalancing = 0; return; case AVLLEFTHEAVY: AVLNode* l = t->lt; switch (bf(l)) { case AVLBALANCED: if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLLEFTHEAVY); set_bf(l, AVLRIGHTHEAVY); _need_rebalancing = 0; t = l; return; case AVLLEFTHEAVY: if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; case AVLRIGHTHEAVY: AVLNode* r = l->rt; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; } } } } void AVLSet::del( item) { if (root == 0) return; _need_rebalancing = 0; _already_found = 0; _found_node = 0; _target_item = &item; _del(root, root); if (_found_node) { delete(_found_node); if (--count == 0) root = 0; } } // build an ordered array of pointers to tree nodes back into a tree // we know that at least one element exists static AVLNode* _do_treeify(int lo, int hi, int& h) { int lh, rh; int mid = (lo + hi) / 2; AVLNode* t = _hold_nodes[mid]; if (lo > mid - 1) { set_lthread(t, 1); if (mid == 0) t->lt = 0; else t->lt = _hold_nodes[mid-1]; lh = 0; } else { set_lthread(t, 0); t->lt = _do_treeify(lo, mid-1, lh); } if (hi < mid + 1) { set_rthread(t, 1); if (mid == _max_hold_index) t->rt = 0; else t->rt = _hold_nodes[mid+1]; rh = 0; } else { set_rthread(t, 0); t->rt = _do_treeify(mid+1, hi, rh); } if (lh == rh) { set_bf(t, AVLBALANCED); h = lh + 1; } else if (lh == rh - 1) { set_bf(t, AVLRIGHTHEAVY); h = rh + 1; } else if (rh == lh - 1) { set_bf(t, AVLLEFTHEAVY); h = lh + 1; } else // can't happen abort(); return t; } static AVLNode* _treeify(int n) { AVLNode* t; if (n == 0) t = 0; else { int b; _max_hold_index = n-1; t = _do_treeify(0, _max_hold_index, b); } delete _hold_nodes; return t; } void AVLSet::_kill(AVLNode* t) { if (t != 0) { if (!lthread(t)) _kill(t->lt); if (!rthread(t)) _kill(t->rt); delete t; } } AVLSet::AVLSet(AVLSet& b) { if ((count = b.count) == 0) { root = 0; } else { _hold_nodes = new AVLNodePtr [count]; AVLNode* t = b.leftmost(); int i = 0; while (t != 0) { _hold_nodes[i++] = new AVLNode(t->item); t = b.succ(t); } root = _treeify(count); } } int AVLSet::operator == (AVLSet& y) { if (count != y.count) return 0; else { AVLNode* t = leftmost(); AVLNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (!(EQ(t->item, u->item))) return 0; else { t = succ(t); u = y.succ(u); } } } } int AVLSet::operator <= (AVLSet& y) { if (count > y.count) return 0; else { AVLNode* t = leftmost(); AVLNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (u == 0) return 0; int cmp = CMP(t->item, u->item); if (cmp == 0) { t = succ(t); u = y.succ(u); } else if (cmp < 0) return 0; else u = y.succ(u); } } } void AVLSet::operator |=(AVLSet& y) { AVLNode* t = leftmost(); AVLNode* u = y.leftmost(); int rsize = count + y.count; _hold_nodes = new AVLNodePtr [rsize]; int k = 0; for (;;) { if (t == 0) { while (u != 0) { _hold_nodes[k++] = new AVLNode(u->item); u = y.succ(u); } break; } else if (u == 0) { while (t != 0) { _hold_nodes[k++] = t; t = succ(t); } break; } int cmp = CMP(t->item, u->item); if (cmp == 0) { _hold_nodes[k++] = t; t = succ(t); u = y.succ(u); } else if (cmp < 0) { _hold_nodes[k++] = t; t = succ(t); } else { _hold_nodes[k++] = new AVLNode(u->item); u = y.succ(u); } } root = _treeify(k); count = k; } void AVLSet::operator &= (AVLSet& y) { AVLNode* t = leftmost(); AVLNode* u = y.leftmost(); int rsize = count AVLNodePtr [rsize]; int k = 0; for (;;) { if (t == 0) break; if (u == 0) { while (t != 0) { AVLNode* tmp = succ(t); delete t; t = tmp; } break; } int cmp = CMP(t->item, u->item); if (cmp == 0) { _hold_nodes[k++] = t; t = succ(t); u = y.succ(u); } else if (cmp < 0) { AVLNode* tmp = succ(t); delete t; t = tmp; } else u = y.succ(u); } root = _treeify(k); count = k; } void AVLSet::operator -=(AVLSet& y) { AVLNode* t = leftmost(); AVLNode* u = y.leftmost(); int rsize = count; _hold_nodes = new AVLNodePtr [rsize]; int k = 0; for (;;) { if (t == 0) break; else if (u == 0) { while (t != 0) { _hold_nodes[k++] = t; t = succ(t); } break; } int cmp = CMP(t->item, u->item); if (cmp == 0) { AVLNode* tmp = succ(t); delete t; t = tmp; u = y.succ(u); } else if (cmp < 0) { _hold_nodes[k++] = t; t = succ(t); } else u = y.succ(u); } root = _treeify(k); count = k; } int AVLSet::owns(Pix i) { if (i == 0) return 0; for (AVLNode* t = leftmost(); t != 0; t = succ(t)) if (Pix(t) == i) return 1; return 0; } int AVLSet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; AVLNode* trail = leftmost(); AVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } t::owns(Pix i) { if (i == 0) return 0; for (AVLNode* t = leftmost(); t != 0; t = succ(t)) if (Pix(t) == i) return 1; return 0; } int AVLSet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; AVLNode* trail = leftmost(); AVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invarianlibg++/g++-include/AVLSet.hP 644 473 0 6517 4677677730 10552 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _AVL_h #pragma once #define _AVL_h 1 #include ".Set.h" struct AVLNode { AVLNode* lt; AVLNode* rt; item; char stat; AVLNode( h, AVLNode* l=0, AVLNode* r=0); ~AVLNode(); }; inline AVLNode::AVLNode( h, AVLNode* l=0, AVLNode* r=0) { item = h; lt = l; rt = r; stat = 0; } inline AVLNode::~AVLNode() {} typedef AVLNode* AVLNodePtr; class AVLSet : public Set { protected: AVLNode* root; AVLSet(AVLNode* p, int l); AVLNode* leftmost(); AVLNode* rightmost(); AVLNode* pred(AVLNode* t); AVLNode* succ(AVLNode* t); void _kill(AVLNode* t); void _add(AVLNode*& t); void _del(AVLNode* p, AVLNode*& t); public: AVLSet(); AVLSet(AVLSet& a); ~AVLSet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item); Pix last(); void prev(Pix& i); void operator |= (AVLSet& b); void operator -= (AVLSet& b); void operator &= (AVLSet& b); int operator == (AVLSet& b); int operator != (AVLSet& b); int operator <= (AVLSet& b); int OK(); }; inline AVLSet::~AVLSet() { _kill(root); } inline AVLSet::AVLSet() { root = 0; count = 0; } inline AVLSet::AVLSet(AVLNode* p, int l) { root = p; count = l; } inline int AVLSet::operator != (AVLSet& b) { return ! ((*this) == b); } inline Pix AVLSet::first() { return Pix(leftmost()); } inline Pix AVLSet::last() { return Pix(rightmost()); } inline void AVLSet::next(Pix& i) { if (i != 0) i = Pix(succ((AVLNode*)i)); } inline void AVLSet::prev(Pix& i) { if (i != 0) i = Pix(pred((AVLNode*)i)); } inline & AVLSet::operator () (Pix i) { if (i == 0) error("null Pix"); return ((AVLNode*)i)->item; } inline void AVLSet::clear() { _kill(root); count = 0; root = 0; } inline int AVLSet::contains( key) { return seek(key) != 0; } #endif t()); } inline Pix AVLSet::last() { return Pix(rightmost()); } inline void AVLSet::next(Pix& i) { if (i != 0) i = Pix(succ((AVLNode*)i)); } inline void AVLSetlibg++/g++-include/AVec.ccP 644 473 0 17705 4677677731 10452 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".AVec.h" /* The following brought to you by the department of redundancy department */ AVec& AVec::operator = (AVec& v) { if (len != 0 && len != v.capacity()) error("nonconformant vectors."); if (len == 0) s = new [len = v.capacity()]; if (s != v.vec()) { for (int i = 0; i < len; ++i) s[i] = v.vec()[i]; } return *this; } AVec& AVec::operator = ( f) { for (int i = 0; i < len; ++i) s[i] = f; return *this; } AVec concat(AVec & a, AVec & b) { int newl = a.capacity() + b.capacity(); * news = new [newl]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while (t < top) *p++ = *t++; top = &(b.vec()[b.capacity()]); t = b.vec(); while (t < top) *p++ = *t++; return AVec(newl, news); } AVec combine(Combiner f, AVec& a, AVec& b) { int newl = a.capacity() * news = new [newl]; * p = news; * top = &(a.vec()[newl]); * t = a.vec(); * u = b.vec(); while (t < top) *p++ = (*f)(*t++, *u++); return AVec(newl, news); } AVec reverse(AVec& a) { * news = new [a.capacity()]; if (a.capacity() != 0) { * lo = news; * hi = &(news[a.capacity() - 1]); while (lo < hi) { tmp = *lo; *lo++ = *hi; *hi-- = tmp; } } return AVec(a.capacity(), news); } AVec map(Mapper f, AVec& a) { * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while(t < top) *p++ = (*f)(*t++); return AVec(a.capacity(), news); } AVec AVec::at(int from = 0, int n = -1) { int to; if (n < 0) { n = len - from; to = len - 1; } else to = from + n - 1; if ((unsigned)from > to) range_error(); * news = new [n]; * p = news; * t = &(s[from]); * top = &(s[to]); while (t <= top) *p++ = *t++; return AVec(n, news); } AVec merge(AVec & a, AVec & b, Comparator f) { int newl = a.capacity() + b.capacity(); * news = new [newl]; * p = news; * topa = &(a.vec()[a.capacity()]); * as = a.vec(); * topb = &(b.vec()[b.capacity()]); * bs = b.vec(); for (;;) { if (as >= topa) { while (bs < topb) *p++ = *bs++; break; } else if (bs >= topb) { while (as < topa) *p++ = *as++; break; } else if ((*f)(*as, *bs) <= 0) *p++ = *as++; else *p++ = *bs++; } return AVec(newl, news); } AVec operator + (AVec& a, AVec& b) { a.check_len(b.capacity()); * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); * u = b.vec(); while (t < top) *p++ = *t++ + *u++; return AVec(a.capacity(), news); } AVec operator - (AVec& a, AVec& b) { a.check_len(b.capacity()); * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); * u = b.vec(); while (t < top) *p++ = *t++ - *u++; return AVec(a.capacity(), news); } AVec product (AVec& a, AVec& b) { a.check_len(b.capacity()); * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); * u = b.vec(); while (t < top) *p++ = *t++ * *u++; return AVec(a.capacity(), news); } AVec quotient(AVec& a, AVec& b) { a.check_len(b.capacity()); * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); * u = b.vec(); while (t < top) *p++ = *t++ / *u++; return AVec(a.capacity(), news); } AVec operator + (AVec& a, b) { * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while (t < top) *p++ = *t++ + b; return AVec(a.capacity(), news); } AVec operator - (AVec& a, b) { * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while (t < top) *p++ = *t++ - b; return AVec(a.capacity(), news); } AVec operator * (AVec& a, b) { * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while (t < top) *p++ = *t++ * b; return AVec(a.capacity(), news); } AVec operator / (AVec& a, b) { * news = new [a.capacity()]; * p = news; * top = &(a.vec()[a.capacity()]); * t = a.vec(); while (t < top) *p++ = *t++ / b; return AVec(a.capacity(), news); } AVec AVec::operator - () { * news = new [len]; * p = news; * top = &(s[len]); * t = s; while (t < top) *p++ = -(*t++); return AVec(len, news); } AVec& AVec::operator += (AVec& b) { check_len(b.capacity()); * u = b.vec(); * top = &(s[len]); * t = s; while (t < top) *t++ += *u++; return *this; } AVec& AVec::operator -= (AVec& b) { check_len(b.capacity()); * u = b.vec(); * top = &(s[len]); * t = s; while (t < top) *t++ -= *u++; return *this; } AVec& AVec::product(AVec& b) { check_len(b.capacity()); * u = b.vec(); * top = &(s[len]); * t = s; while (t < top) *t++ *= *u++; return *this; } AVec& AVec::quotient(AVec& b) { check_len(b.capacity()); * u = b.vec(); * top = &(s[len]); * t = s; while (t < top) *t++ /= *u++; return *this; } AVec& AVec::operator += ( b) { * top = &(s[len]); * t = s; while (t < top) *t++ += b; return *this; } AVec& AVec::operator -= ( b) { * top = &(s[len]); * t = s; while (t < top) *t++ -= b; return *this; } AVec& AVec::operator *= ( b) { * top = &(s[len]); * t = s; while (t < top) *t++ *= b; return *this; } AVec& AVec::operator /= ( b) { * top = &(s[len]); * t = s; while (t < top) *t++ /= b; return *this; } AVec::max() { if (len == 0) return 0; * top = &(s[len]); * t = s; res = *t++; for (; t < top; ++t) if (*t > res) res = *t; return res; } int AVec::max_index() { if (len == 0) return -1; int ind = 0; for (int i = 1; i < len; ++i) if (s[i] > s[ind]) ind = i; return ind; } AVec::min() { if (len == 0) return 0; * top = &(s[len]); * t = s; res = *t++; for (; t < top; ++t) if (*t < res) res = *t; return res; } int AVec::min_index() { if (len == 0) return -1; int ind = 0; for (int i = 1; i < len; ++i) if (s[i] < s[ind]) ind = i; return ind; } AVec::sum() { res = 0; * top = &(s[len]); * t = s; while (t < top) res += *t++; return res; } AVec::sumsq() { res = 0; * top = &(s[len]); * t = s; for (; t < top; ++t) res += *t * *t; return res; } operator * (AVec& a, AVec& b) { a.check_len(b.capacity()); * top = &(a.vec()[a.capacity()]); * t = a.vec(); * u = b.vec(); res = 0; while (t < top) res += *t++ * *u++; return res; } ind]) ind = i; return ind; } AVec::sum() { libg++/g++-include/BSTSet.ccP 644 473 0 16142 4677677731 10732 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".BSTSet.h" /* traversal primitives */ BSTNode* BSTSet::leftmost() { BSTNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } BSTNode* BSTSet::rightmost() { BSTNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } BSTNode* BSTSet::succ(BSTNode* t) { if (t == 0) return 0; if (t->rt != 0) { t = t->rt; while (t->lt != 0) t = t->lt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->lt) return t->par; else t = t->par; } } } BSTNode* BSTSet::pred(BSTNode* t) { if (t == 0) return 0; else if (t->lt != 0) { t = t->lt; while (t->rt != 0) t = t->rt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->rt) return t->par; else t = t->par; } } } Pix BSTSet::seek( key) { BSTNode* t = root; for (;;) { if (t == 0) return 0; int comp = CMP(key, t->item); if (comp == 0) return Pix(t); else if (comp < 0) t = t->lt; else t = t->rt; } } Pix BSTSet::add( item) { if (root == 0) { ++count; root = new BSTNode(item); return Pix(root); } BSTNode* t = root; BSTNode* p = root; int comp; for (;;) { if (t == 0) { ++count; t = new BSTNode(item); if (comp > 0) p->lt = t; else p->rt = t; t->par = p; return Pix(t); } p = t; comp = CMP(t->item, item); if (comp == 0) return Pix(t); else if (comp > 0) t = t->lt; else t = t->rt; } } void BSTSet::del( key) { BSTNode* t = root; BSTNode* p = root; int comp; for (;;) { if (t == 0) return; comp = CMP(key, t->item); if (comp == 0) { --count; BSTNode* repl; if (t->lt == 0) repl = t->rt; else if (t->rt == 0) repl = t->lt; else { BSTNode* prepl = t; repl = t->lt; while (repl->rt != 0) { prepl = repl; repl = repl->rt; } if (prepl != t) { prepl->rt = repl->lt; if (prepl->rt != 0) prepl->rt->par = prepl; repl->lt = t->lt; if (repl->lt != 0) repl->lt->par = repl; } repl->rt = t->rt; if (repl->rt != 0) repl->rt->par = repl; } if (t == root) { root = repl; if (repl != 0) repl->par = 0; } else { if (t == p->lt) p->lt = repl; else p->rt = repl; if (repl != 0) repl->par = p; } delete t; return; } p = t; if (comp < 0) t = t->lt; else t = t->rt; } } void BSTSet::_kill(BSTNode* t) { if (t != 0) { _kill(t->lt); _kill(t->rt); delete t; } } BSTNode* BSTSet::_copy(BSTNode* t) { if (t == 0) return 0; else { BSTNode* u = new BSTNode(t->item, _copy(t->lt), _copy(t->rt)); if (u->lt != 0) u->lt->par = u; if (u->rt != 0) u->rt->par = u; return u; } } int BSTSet::operator == (BSTSet& y) { if (count != y.count) return 0; else { BSTNode* t = leftmost(); BSTNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (!EQ(t->item, u->item)) return 0; else { t = succ(t); u = y.succ(u); } } } } int BSTSet::operator <= (BSTSet& y) { if (count > y.count) return 0; else { BSTNode* t = leftmost(); BSTNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (u == 0) return 0; int cmp = CMP(t->item, u->item); if (cmp == 0) { t = succ(t); u = y.succ(u); } else if (cmp < 0) return 0; else u = y.succ(u); } } } // linear-time, zero space overhead binary tree rebalancing from // Stout & Warren, ``Tree rebalancing in linear space and time'' // CACM, Sept, 1986, p902. void BSTSet::balance() { if (count <= 2) return; // don't bother -- // also we assume non-null root, below // make re-attaching the root easy via trickery struct _fake_node { _fake_node *lt, *rt, *par; } fake_root; fake_root.rt = (_fake_node*)root; fake_root.par = 0; BSTNode* pseudo_root = (BSTNode*)&fake_root; // phase 1: tree-to-vine BSTNode* vine_tail = pseudo_root; BSTNode* remainder = root; while (remainder != 0) { if (remainder->lt == 0) { vine_tail = remainder; remainder = remainder->rt; } else { BSTNode* tmp = remainder->lt; remainder->lt = tmp->rt; if (remainder->lt != 0) remainder->lt->par = remainder; tmp->rt = remainder; remainder->par = tmp; vine_tail->rt = remainder = tmp; } } // phase 2: vine-to-tree // Uses the slightly simpler version adapted from // Day ``Balancing a binary tree'' Computer Journal, Nov. 1976, // since it's not generally important whether the `stray' leaves are // on the left or on the right. unsigned int spines = count - 1; while (spines > 1) { int compressions = spines >> 1; // compress every other node spines -= compressions + 1; // halve for next time BSTNode* scanner = pseudo_root; while (compressions-- > 0) { BSTNode* child = scanner->rt; BSTNode* grandchild = child->rt; scanner->rt = grandchild; grandchild->par = scanner; child->rt = grandchild->lt; if (child->rt != 0) child->rt->par = child; grandchild->lt = child; child->par = grandchild; scanner = grandchild; } } root = pseudo_root->rt; root->par = 0; } int BSTSet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; BSTNode* trail = leftmost(); BSTNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } grandchild->lt = child; child->par = grandchild; scanner = grandchild; } } root = pseudo_root->rt; root->par = 0; } int BSTSet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; BSTNode* trail = leftmost(); BSTNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; libg++/g++-include/BSTSet.hP 644 473 0 6471 4677677731 10560 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _BSTSet_h #pragma once #define _BSTSet_h 1 #include ".Set.h" #ifndef _BSTNode #define _BSTNode 1 struct BSTNode { BSTNode* lt; BSTNode* rt; BSTNode* par; item; BSTNode( h, BSTNode* l=0, BSTNode* r=0, BSTNode* p = 0); ~BSTNode(); }; inline BSTNode::BSTNode( h, BSTNode* l=0, BSTNode* r=0, BSTNode* p = 0) { item = h; lt = l; rt = r; par = p; } inline BSTNode::~BSTNode() {} typedef BSTNode* BSTNodePtr; #endif class BSTSet : public Set { protected: BSTNode* root; BSTNode* leftmost(); BSTNode* rightmost(); BSTNode* pred(BSTNode* t); BSTNode* succ(BSTNode* t); void _kill(BSTNode* t); BSTNode* _copy(BSTNode* t); public: BSTSet(); BSTSet(BSTSet& a); ~BSTSet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item); Pix last(); void prev(Pix& i); int operator == (BSTSet& b); int operator != (BSTSet& b); int operator <= (BSTSet& b); void balance(); int OK(); }; inline BSTSet::~BSTSet() { _kill(root); } inline BSTSet::BSTSet() { root = 0; count = 0; } inline BSTSet::BSTSet(BSTSet& a) { count = a.count; root = _copy(a.root); } inline int BSTSet::operator != (BSTSet& b) { return ! (*this == b); } inline Pix BSTSet::first() { return Pix(leftmost()); } inline Pix BSTSet::last() { return Pix(rightmost()); } inline void BSTSet::next(Pix& i) { if (i != 0) i = Pix(succ((BSTNode*)i)); } inline void BSTSet::prev(Pix& i) { if (i != 0) i = Pix(pred((BSTNode*)i)); } inline & BSTSet::operator () (Pix i) { if (i == 0) error("null Pix"); return ((BSTNode*)i)->item; } inline void BSTSet::clear() { _kill(root); count = 0; root = 0; } inline int BSTSet::contains( key) { return seek(key) != 0; } #endif st()); } inline Pix BSTSet::last() { return Pix(rightmost()); } inline void BSTSet::next(Pix& i) { if (i != 0) i = Pix(succ((BSTNode*)i)); } inline void BSTSet::prev(Pix& i) { iflibg++/g++-include/Bag.ccP 644 473 0 3235 4677677731 10276 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".Bag.h" // error handling void Bag::error(const char* msg) { (*lib_error_handler)("Bag", msg); } Pix Bag::seek( item, Pix i = 0) { if (i == 0) i = first(); else next(i); for (;i != 0 && (!(EQ((*this)(i), item))); next(i)); return i; } int Bag::owns(Pix p) { if (p == 0) return 0; for (Pix i = first(); i != 0; next(i)) if (i == p) return 1; return 0; } void Bag::remove( item) { int i = nof(item); while (i-- > 0) del(item); } int Bag::nof( item) { int n = 0; for (Pix p = first(); p; next(p)) if (EQ((*this)(p), item)) ++n; return n; } void Bag::clear() { Pix i = first(); while (i != 0) { del((*this)(i)); i = first(); } } 0 && (!(EQ((*this)(i), item))); next(i)); return i; } int Bag::owns(Pix p) { if (p == 0) return 0; for (Pix i = first(); i != 0; next(i)) if (i == p) return 1; return 0; } void Bag::remove( item) { int i = nof(item); while (i-- > 0) del(item); } int Bag::nof( item) { int n = 0; for (Pix p = first(); p; next(p)) iflibg++/g++-include/Bag.hP 644 473 0 4406 4677677731 10141 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Bag_h #pragma once #define _Bag_h 1 #include #include ".defs.h" class Bag { protected: int count; public: int length(); // current number of items int empty(); virtual Pix add( item) = 0; // add item; return Pix virtual void del( item) = 0; // delete 1 occurrence of item virtual void remove( item); // delete all occurrences virtual void clear(); // delete all items virtual int contains( item); // is item in Bag? virtual int nof( item); // how many in Bag? virtual Pix first() = 0; // Pix of first item or 0 virtual void next(Pix& i) = 0; // advance to next or 0 virtual & operator () (Pix i) = 0; // access item at i virtual Pix seek( item, Pix from=0); // Pix of next occurrence virtual int owns(Pix i); // is i a valid Pix ? void error(const char* msg); virtual int OK() = 0; // rep invariant }; inline int Bag::length() { return count; } inline int Bag::empty() { return count == 0; } inline int Bag::contains( item) { return seek(item) != 0; } #endif l & operator () (Pix i) = 0; // access item at i virtual Pix seek( item, Pix from=0); // Pix of next occurrence virtual int owns(Pix i); // is i a valid Pix ? void error(const libg++/g++-include/CHBag.ccP 644 473 0 10453 4677677732 10532 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".CHBag.h" // The nodes are linked together serially via a version // of a trick used in some vtables: odd pointers are // actually links to the next table entry. // Not terrible, but not wonderful either static inline int goodCHptr(CHNode* t) { return ((((unsigned)t) & 1) == 0); } static inline CHNode* index_to_CHptr(int i) { return (CHNode*)((i << 1) + 1); } static inline int CHptr_to_index(CHNode* t) { return ( ((unsigned) t) >> 1); } CHBag::CHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY) { tab = (CHNode**)(new CHNodePtr[size = sz]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; } CHBag::CHBag(CHBag& a) { tab = (CHNode**)(new CHNodePtr[size = a.size]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; for (Pix p = a.first(); p; a.next(p)) add(a(p)); } Pix CHBag::seek( key, Pix i = 0) { CHNode* p = (CHNode*)i; if (p == 0 || !EQ(p->hd, key)) { unsigned int h = HASH(key) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(key, t->hd)) return Pix(t); } else { for (p = p->tl; goodCHptr(p); p = p->tl) if (EQ(p->hd, key)) return Pix(p); } return 0; } int CHBag::nof( key) { int n = 0; unsigned int h = HASH(key) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(key, t->hd)) ++n; return n; } Pix CHBag::add( item) { unsigned int h = HASH(item) % size; CHNode* t = new CHNode(item); t->tl = tab[h]; tab[h] = t; ++count; return Pix(t); } void CHBag::del( key) { unsigned int h = HASH(key) % size; CHNode* t = tab[h]; CHNode* trail = t; while (goodCHptr(t)) { if (EQ(key, t->hd)) { if (trail == t) tab[h] = t->tl; else trail->tl = t->tl; delete t; --count; return; } trail = t; t = t->tl; } } void CHBag::remove( key) { unsigned int h = HASH(key) % size; CHNode* t = tab[h]; CHNode* trail = t; while (goodCHptr(t)) { if (EQ(key, t->hd)) { --count; if (trail == t) { tab[h] = t->tl; delete t; t = trail = tab[h]; } else { trail->tl = t->tl; delete t; t = trail->tl; } } else { trail = t; t = t->tl; } } } void CHBag::clear() { for (unsigned int i = 0; i < size; ++i) { CHNode* p = tab[i]; tab[i] = index_to_CHptr(i+1); while (goodCHptr(p)) { CHNode* nxt = p->tl; delete(p); p = nxt; } } count = 0; } Pix CHBag::first() { for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); return 0; } void CHBag::next(Pix& p) { if (p == 0) return; CHNode* t = ((CHNode*)p)->tl; if (goodCHptr(t)) p = Pix(t); else { for (unsigned int i = CHptr_to_index(t); i < size; ++i) { if (goodCHptr(tab[i])) { p = Pix(tab[i]); return; } } p = 0; } } int CHBag::OK() { int v = tab != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { for (CHNode* p = tab[i]; goodCHptr(p); p = p->tl) ++n; v &= CHptr_to_index(p) == i + 1; } v &= count == n; if (!v) error("invariant failure"); return v; } ode*)p)->tl; if (goodCHptr(t)) p = Pix(t); else { for (unsigned int i = CHptr_to_index(t); i < size; ++i) { if (goodCHptr(tab[i])) { p = Pix(tab[i]); return; }libg++/g++-include/CHBag.hP 644 473 0 4366 4677677732 10362 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _CHBag_h #pragma once #define _CHBag_h 1 #include ".Bag.h" #ifndef _CHNode_h #define _CHNode_h 1 struct CHNode { CHNode* tl; hd; CHNode(); CHNode( h, CHNode* t = 0); ~CHNode(); }; inline CHNode::CHNode() {} inline CHNode::CHNode( h, CHNode* t = 0) { hd = h; tl = t; } inline CHNode::~CHNode() {} typedef CHNode* CHNodePtr; #endif class CHBag : public Bag { protected: CHNode** tab; unsigned int size; public: CHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY); CHBag(CHBag& a); ~CHBag(); Pix add( item); void del( item); void remove(item); int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item, Pix from = 0); int OK(); }; inline CHBag::~CHBag() { clear(); delete tab; } inline int CHBag::contains( key) { return seek(key) != 0; } inline & CHBag::operator () (Pix i) { if (i == 0) error("null Pix"); return ((CHNode*)i)->hd; } #endif ; int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item, Pix from = 0); int OK(); }; ilibg++/g++-include/CHMap.ccP 644 473 0 7264 4677677732 10544 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include "..CHMap.h" // The nodes are linked together serially via a version // of a trick used in some vtables: odd pointers are // actually links to the next table entry. // Not terrible, but not wonderful either static inline int goodCHptr(CHNode* t) { return ((((unsigned)t) & 1) == 0); } static inline CHNode* index_to_CHptr(int i) { return (CHNode*)((i << 1) + 1); } static inline int CHptr_to_index(CHNode* t) { return ( ((unsigned) t) >> 1); } CHMap::CHMap( dflt, unsigned int sz = DEFAULT_INITIAL_CAPACITY) :(dflt) { tab = (CHNode**)(new CHNodePtr[size = sz]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; } CHMap::CHMap(CHMap& a) :(a.def) { tab = (CHNode**)(new CHNodePtr[size = a.size]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p); } Pix CHMap::seek( key) { unsigned int h = HASH(key) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(key, t->hd)) return Pix(t); return 0; } & CHMap::operator []( item) { unsigned int h = HASH(item) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(item, t->hd)) return t->cont; t = new CHNode(item, def, tab[h]); tab[h] = t; ++count; return t->cont; } void CHMap::del( key) { unsigned int h = HASH(key) % size; CHNode* t = tab[h]; CHNode* trail = t; while (goodCHptr(t)) { if (EQ(key, t->hd)) { if (trail == t) tab[h] = t->tl; else trail->tl = t->tl; delete t; --count; return; } trail = t; t = t->tl; } } void CHMap::clear() { for (unsigned int i = 0; i < size; ++i) { CHNode* p = tab[i]; tab[i] = index_to_CHptr(i+1); while (goodCHptr(p)) { CHNode* nxt = p->tl; delete(p); p = nxt; } } count = 0; } Pix CHMap::first() { for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); return 0; } void CHMap::next(Pix& p) { CHNode* t = ((CHNode*)p)->tl; if (goodCHptr(t)) p = Pix(t); else { for (unsigned int i = CHptr_to_index(t); i < size; ++i) { if (goodCHptr(tab[i])) { p = Pix(tab[i]); return; } } p = 0; } } int CHMap::OK() { int v = tab != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { for (CHNode* p = tab[i]; goodCHptr(p); p = p->tl) ++n; v &= CHptr_to_index(p) == i + 1; } v &= count == n; if (!v) error("invariant failure"); return v; } ->tl; if (goodCHptr(t)) p = Pix(t); else { for (unsigned int i = CHptr_to_index(t); i < size; ++i) { if (goodCHptr(tab[i])) { p = Pix(tab[i]); return; } } p = 0; } } int CHMap::OK() { int v = tab != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) libg++/g++-include/CHMap.hP 644 473 0 4677 4677677732 10413 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _CHMap_h #pragma once #define _CHMap_h 1 #include "..Map.h" #ifndef _CHNode_h #define _CHNode_h 1 struct CHNode { CHNode* tl; hd; cont; CHNode(); CHNode( h, c, CHNode* t = 0); ~CHNode(); }; inline CHNode::CHNode() {} inline CHNode::CHNode( h, c, CHNode* t = 0) : hd(h), cont(c), tl(t) {} inline CHNode::~CHNode() {} typedef CHNode* CHNodePtr; #endif class CHMap : public Map { protected: CHNode** tab; unsigned int size; public: CHMap( dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY); CHMap(CHMap& a); ~CHMap(); & operator [] ( key); void del( key); Pix first(); void next(Pix& i); & key(Pix i); & contents(Pix i); Pix seek( key); int contains( key); void clear(); int OK(); }; inline CHMap::~CHMap() { clear(); delete tab; } inline int CHMap::contains( key) { return seek(key) != 0; } inline & CHMap::key(Pix p) { if (p == 0) error("null Pix"); return ((CHNode*)p)->hd; } inline & CHMap::contents(Pix p) { if (p == 0) error("null Pix"); return ((CHNode*)p)->cont; } #endif contents(Pix i); Pix seek( key); int libg++/g++-include/CHSet.ccP 644 473 0 13773 4677677732 10604 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".CHSet.h" // A CHSet is implemented as an array (tab) of buckets, each of which // contains a pointer to a list of CHNodes. Each node contains a // pointer to the next node in the list, and a pointer to the . // The end of the list is marked by a next node pointer which is odd // when considered as an integer (least significant bit = 1). The // assumption is that CHNodes will all begin on even addresses. If // the odd pointer is right-shifted by one bit, it becomes the index // within the tab array of the next bucket (that is, bucket i has // next bucket pointer 2*(i+1)+1). // The bucket pointers are initialized by the constructor and // used to support the next(Pix&) method. // This implementation is not portable to machines with different // pointer and integer sizes, or on which CHNodes might be aligned on // odd byte boundaries, but allows the same pointer to be used for // chaining within a bucket and to the next bucket. static inline int goodCHptr(CHNode* t) { return ((((unsigned)t) & 1) == 0); } static inline CHNode* index_to_CHptr(int i) { return (CHNode*)((i << 1) + 1); } static inline int CHptr_to_index(CHNode* t) { return ( ((unsigned) t) >> 1); } CHSet::CHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY) { tab = (CHNode**)(new CHNodePtr[size = sz]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; } CHSet::CHSet(CHSet& a) { tab = (CHNode**)(new CHNodePtr[size = a.size]); for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); count = 0; for (Pix p = a.first(); p; a.next(p)) add(a(p)); } Pix CHSet::seek( key) { unsigned int h = HASH(key) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(key, t->hd)) return Pix(t); return 0; } Pix CHSet::add( item) { unsigned int h = HASH(item) % size; for (CHNode* t = tab[h]; goodCHptr(t); t = t->tl) if (EQ(item, t->hd)) return Pix(t); ++count; t = new CHNode(item, tab[h]); tab[h] = t; return Pix(t); } void CHSet::del( key) { unsigned int h = HASH(key) % size; CHNode* t = tab[h]; CHNode* trail = t; while (goodCHptr(t)) { if (EQ(key, t->hd)) { if (trail == t) tab[h] = t->tl; else trail->tl = t->tl; delete t; --count; return; } trail = t; t = t->tl; } } void CHSet::clear() { for (unsigned int i = 0; i < size; ++i) { CHNode* p = tab[i]; tab[i] = index_to_CHptr(i+1); while (goodCHptr(p)) { CHNode* nxt = p->tl; delete(p); p = nxt; } } count = 0; } Pix CHSet::first() { for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); return 0; } void CHSet::next(Pix& p) { if (p == 0) return; CHNode* t = ((CHNode*)p)->tl; if (goodCHptr(t)) p = Pix(t); else { for (unsigned int i = CHptr_to_index(t); i < size; ++i) { if (goodCHptr(tab[i])) { p = Pix(tab[i]); return; } } p = 0; } } int CHSet::operator == (CHSet& b) { if (count != b.count) return 0; else { CHNode* p; for (unsigned int i = 0; i < size; ++i) for (p = tab[i]; goodCHptr(p); p = p->tl) if (b.seek(p->hd) == 0) return 0; for (i = 0; i < b.size; ++i) for (p = b.tab[i]; goodCHptr(p); p = p->tl) if (seek(p->hd) == 0) return 0; return 1; } } int CHSet::operator <= (CHSet& b) { if (count > b.count) return 0; else { for (unsigned int i = 0; i < size; ++i) for (CHNode* p = tab[i]; goodCHptr(p); p = p->tl) if (b.seek(p->hd) == 0) return 0; return 1; } } void CHSet::operator |= (CHSet& b) { if (&b == this || b.count == 0) return; for (unsigned int i = 0; i < b.size; ++i) for (CHNode* p = b.tab[i]; goodCHptr(p); p = p->tl) add(p->hd); } void CHSet::operator &= (CHSet& b) { for (unsigned int i = 0; i < size; ++i) { CHNode* t = tab[i]; CHNode* trail = t; while (goodCHptr(t)) { CHNode* nxt = t->tl; if (b.seek(t->hd) == 0) { if (trail == tab[i]) trail = tab[i] = nxt; else trail->tl = nxt; delete t; --count; } else trail = t; t = nxt; } } } void CHSet::operator -= (CHSet& b) { for (unsigned int i = 0; i < size; ++i) { CHNode* t = tab[i]; CHNode* trail = t; while (goodCHptr(t)) { CHNode* nxt = t->tl; if (b.seek(t->hd) != 0) { if (trail == tab[i]) trail = tab[i] = nxt; else trail->tl = nxt; delete t; --count; } else trail = t; t = nxt; } } } int CHSet::OK() { int v = tab != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { for (CHNode* p = tab[i]; goodCHptr(p); p = p->tl) ++n; v &= CHptr_to_index(p) == i + 1; } v &= count == n; if (!v) error("invariant failure"); return v; } ilibg++/g++-include/CHSet.hP 644 473 0 4772 4677677732 10425 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _CHSet_h #pragma once #define _CHSet_h 1 #include ".Set.h" #ifndef _CHNode_h #define _CHNode_h 1 struct CHNode { CHNode* tl; hd; CHNode(); CHNode( h, CHNode* t = 0); ~CHNode(); }; inline CHNode::CHNode() {} inline CHNode::CHNode( h, CHNode* t = 0) { hd = h; tl = t; } inline CHNode::~CHNode() {} typedef CHNode* CHNodePtr; #endif class CHSet : public Set { protected: CHNode** tab; unsigned int size; public: CHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY); CHSet(CHSet& a); ~CHSet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item); void operator |= (CHSet& b); void operator -= (CHSet& b); void operator &= (CHSet& b); int operator == (CHSet& b); int operator != (CHSet& b); int operator <= (CHSet& b); int OK(); }; inline CHSet::~CHSet() { clear(); delete tab; } inline int CHSet::contains( key) { return seek(key) != 0; } inline & CHSet::operator () (Pix i) { if (i == 0) error("null Pix"); return ((CHNode*)i)->hd; } inline int CHSet::operator != (CHSet& b) { return ! ((*this) == b); } #endif operatlibg++/g++-include/DLDeque.hP 644 473 0 5001 4677677733 10725 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _DLDeque_h #pragma once #define _DLDeque_h #include ".DLList.h" #include ".Deque.h" class DLDeque : public Deque { DLList p; public: DLDeque(); DLDeque(const DLDeque& d); ~DLDeque(); void operator = (const DLDeque&); void push( item); // insert at front void enq( item); // insert at rear & front(); & rear(); deq(); void del_front(); void del_rear(); void clear(); int empty(); int full(); int length(); int OK(); }; inline DLDeque::DLDeque() : p() {} inline DLDeque::DLDeque(const DLDeque& d) : p(d.p) {} inline DLDeque::~DLDeque() {} inline void DLDeque::push(item) { p.prepend(item); } inline void DLDeque::enq(item) { p.append(item); } inline DLDeque::deq() { return p.remove_front(); } inline & DLDeque::front() { return p.front(); } inline & DLDeque::rear() { return p.rear(); } inline void DLDeque::del_front() { p.del_front(); } inline void DLDeque::del_rear() { p.del_rear(); } inline void DLDeque::operator =(const DLDeque& s) { p.operator = (s.p); } inline int DLDeque::empty() { return p.empty(); } inline int DLDeque::full() { return 0; } inline int DLDeque::length() { return p.length(); } inline int DLDeque::OK() { return p.OK(); } inline void DLDeque::clear() { p.clear(); } #endif >& DLDeque::rear() { return p.rear(); } inline void DLDeque::del_front() { p.del_front(); } inline void DLDeque::del_rear() { p.del_rear(); } inline void DLDeque::operator =(const DLDeque& s) { p.operator = (s.p); } inline int DLDeque::empty() { return p.empty(); } inline int DLDeque::full() { return 0; } inline int DLDeque::length() { return p.length(); } inline int DLDeque::OK() { return p.OK(); } inline void DLDeque::clear() { p.clear(); } #endiflibg++/g++-include/DLList.ccP 644 473 0 12163 4677677733 10762 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include ".DLList.h" // error handling void DLList::error(const char* msg) { (*lib_error_handler)("DLList", msg); } DLList::DLList(DLList& a) { if (a.h == 0) h = 0; else { DLListNode* p = a.h; DLListNode* t = new DLListNode(p->hd); h = t; p = p->fd; while (p != a.h) { DLListNode* n = new DLListNode(p->hd); t->fd = n; n->bk = t; t = n; p = p->fd; } t->fd = h; h->bk = t; return; } } DLList& DLList::operator = (DLList& a) { if (h != a.h) { clear(); if (a.h != 0) { DLListNode* p = a.h; DLListNode* t = new DLListNode(p->hd); h = t; p = p->fd; while (p != a.h) { DLListNode* n = new DLListNode(p->hd); t->fd = n; n->bk = t; t = n; p = p->fd; } t->fd = h; h->bk = t; } } return *this; } void DLList::clear() { if (h == 0) return; DLListNode* p = h->fd; h->fd = 0; h = 0; while (p != 0) { DLListNode* nxt = p->fd; delete(p); p = nxt; } } Pix DLList::prepend( item) { DLListNode* t = new DLListNode(item); if (h == 0) t->fd = t->bk = h = t; else { t->fd = h; t->bk = h->bk; h->bk->fd = t; h->bk = t; h = t; } return Pix(t); } Pix DLList::append( item) { DLListNode* t = new DLListNode(item); if (h == 0) t->fd = t->bk = h = t; else { t->bk = h->bk; t->bk->fd = t; t->fd = h; h->bk = t; } return Pix(t); } Pix DLList::ins_after(Pix p, item) { if (p == 0) error("null Pix"); DLListNode* u = (DLListNode*) p; DLListNode* t = new DLListNode(item, u, u->fd); u->fd->bk = t; u->fd = t; return Pix(t); } Pix DLList::ins_before(Pix p, item) { if (p == 0) error("null Pix"); DLListNode* u = (DLListNode*) p; DLListNode* t = new DLListNode(item, u->bk, u); u->bk->fd = t; u->bk = t; if (u == h) h = t; return Pix(t); } void DLList::join(DLList& b) { DLListNode* t = b.h; b.h = 0; if (h == 0) h = t; else if (t != 0) { DLListNode* l = t->bk; h->bk->fd = t; t->bk = h->bk; h->bk = l; l->fd = h; } } int DLList::owns(Pix p) { DLListNode* t = h; if (t != 0 && p != 0) { do { if (Pix(t) == p) return 1; t = t->fd; } while (t != h); } return 0; } void DLList::del(Pix& p, int dir = 1) { if (p == 0) error("null Pix"); DLListNode* t = (DLListNode*) p; if (t->fd == t) { h = 0; p = 0; } else { if (dir < 0) { if (t == h) p = 0; else p = Pix(t->bk); } else { if (t == h->bk) p = 0; else p = Pix(t->fd); } t->bk->fd = t->fd; t->fd->bk = t->bk; if (t == h) h = t->fd; } delete t; } DLList::remove_front() { if (h == 0) error("remove_front of empty list"); DLListNode* t = h; res = t->hd; if (h->fd == h) h = 0; else { h->fd->bk = h->bk; h->bk->fd = h->fd; h = h->fd; } delete t; return res; } void DLList::del_front() { if (h == 0) error("del_front of empty list"); DLListNode* t = h; if (h->fd == h) h = 0; else { h->fd->bk = h->bk; h->bk->fd = h->fd; h = h->fd; } delete t; } DLList::remove_rear() { if (h == 0) error("remove_rear of empty list"); DLListNode* t = h->bk; res = t->hd; if (h->fd == h) h = 0; else { t->fd->bk = t->bk; t->bk->fd = t->fd; } delete t; return res; } void DLList::del_rear() { if (h == 0) error("del_rear of empty list"); DLListNode* t = h->bk; if (h->fd == h) h = 0; else { t->fd->bk = t->bk; t->bk->fd = t->fd; } delete t; } int DLList::OK() { int v = 1; if (h != 0) { DLListNode* t = h; long count = MAXLONG; // Lots of chances to find h! do { count--; v &= t->bk->fd == t; v &= t->fd->bk == t; t = t->fd; } while (v && count > 0 && t != h); v &= count > 0; } if (!v) error("invariant failure"); return v; } _rear of empty list"); DLListNode* t = h->bk; if (h->fd == h) h = 0; else { t->fd->bk = t->bk; t->bk->fd = t->fd; } delete t; } int DLList::OK() { int v = 1; if (h != 0) { DLListNode* t = h; long count = MAXLONG; // Lots of chances to find h! do { count--; v &= t->bk->fd == t; v &= t->fd->bk == t; t = t->fd; libg++/g++-include/DLList.hP 644 473 0 7424 4677677733 10610 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _DLList_h #pragma once #define _DLList_h 1 #include #include ".defs.h" #ifndef _DLListNode_h #define _DLListNode_h 1 struct DLListNode { DLListNode* bk; DLListNode* fd; hd; DLListNode(); DLListNode( h, DLListNode* p = 0, DLListNode* n = 0); ~DLListNode(); }; inline DLListNode::DLListNode() {} inline DLListNode::DLListNode( h, DLListNode* p = 0, DLListNode* n = 0) { hd = h; bk = p; fd = n; } inline DLListNode::~DLListNode() {} typedef DLListNode* DLListNodePtr; #endif class DLList { friend class DLListTrav; DLListNode* h; public: DLList(); DLList(DLList& a); ~DLList(); DLList& operator = (DLList& a); int empty(); int length(); void clear(); Pix prepend( item); Pix append( item); void join(DLList&); & front(); remove_front(); void del_front(); & rear(); remove_rear(); void del_rear(); & operator () (Pix p); Pix first(); Pix last(); void next(Pix& p); void prev(Pix& p); int owns(Pix p); Pix ins_after(Pix p, item); Pix ins_before(Pix p, item); void del(Pix& p, int dir = 1); void error(const char* msg); int OK(); }; inline DLList::~DLList() { clear(); } inline DLList::DLList() { h = 0; } inline int DLList::empty() { return h == 0; } inline int DLList::length() { int l = 0; DLListNode* t = h; if (t != 0) do { ++l; t = t->fd; } while (t != h); return l; } inline void DLList::next(Pix& p) { p = (p == 0 || p == h->bk)? 0 : Pix(((DLListNode*)p)->fd); } inline void DLList::prev(Pix& p) { p = (p == 0 || p == h)? 0 : Pix(((DLListNode*)p)->bk); } inline Pix DLList::first() { return Pix(h); } inline Pix DLList::last() { return (h == 0)? 0 : Pix(h->bk); } inline & DLList::operator () (Pix p) { if (p == 0) error("null Pix"); return ((DLListNode*)p)->hd; } inline & DLList::front() { if (h == 0) error("front: empty list"); return h->hd; } inline & DLList::rear() { if (h == 0) error("rear: empty list"); return h->bk->hd; } #endif ev(Pix& p) { p = (p == 0 || p == h)? 0 : Pix(((DLListNode*)p)->bk); } inline Pix DLList::first() { return Pix(h); } inline Pix DLList::last() { return (h == 0)? 0 : Pix(h->bk); } inline & DLList::operator () (Pixlibg++/g++-include/SplayPQ.ccP 644 473 0 23345 4677677733 11164 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include ".SplayPQ.h" /* struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985 splay tree algorithms All routines use a version of their `simple top-down' splay alg. (p 669) */ struct _dummySplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; } _dummy_null; /* traversal primitives */ SplayNode* SplayPQ::leftmost() { SplayNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } SplayNode* SplayPQ::rightmost() { SplayNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } SplayNode* SplayPQ::succ(SplayNode* t) { if (t == 0) return 0; if (t->rt != 0) { t = t->rt; while (t->lt != 0) t = t->lt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->lt) return t->par; else t = t->par; } } } SplayNode* SplayPQ::pred(SplayNode* t) { if (t == 0) return 0; else if (t->lt != 0) { t = t->lt; while (t->rt != 0) t = t->rt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->rt) return t->par; else t = t->par; } } } Pix SplayPQ::seek( key) { SplayNode* t = root; if (t == 0) return 0; int comp = CMP(key, t->item); if (comp == 0) return Pix(t); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) break; else { comp = CMP(key, tr->item); if (comp <= 0 || tr->rt == 0) { l->rt = t; t->par = l; l = t; t = tr; if (comp >= 0) break; } else { if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = tr->rt; comp = CMP(key, t->item); } } } else { SplayNode* tl = t->lt; if (tl == 0) break; else { comp = CMP(key, tl->item); if (comp >= 0 || tl->lt == 0) { r->lt = t; t->par = r; r = t; t = tl; if (comp <= 0) break; } else { if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tl->lt; comp = CMP(key, t->item); } } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return (comp == 0) ? Pix(t) : 0; } Pix SplayPQ::enq( item) { ++count; SplayNode* newnode = new SplayNode(item); SplayNode* t = root; if (t == 0) { root = newnode; return Pix(root); } int comp = CMP(item, t->item); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; int done = 0; while (!done) { if (comp >= 0) { SplayNode* tr = t->rt; if (tr == 0) { tr = newnode; comp = 0; done = 1; } else comp = CMP(item, tr->item); if (comp <= 0) { l->rt = t; t->par = l; l = t; t = tr; } else { SplayNode* trr = tr->rt; if (trr == 0) { trr = newnode; comp = 0; done = 1; } else comp = CMP(item, trr->item); if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = trr; } } else { SplayNode* tl = t->lt; if (tl == 0) { tl = newnode; comp = 0; done = 1; } else comp = CMP(item, tl->item); if (comp >= 0) { r->lt = t; t->par = r; r = t; t = tl; } else { SplayNode* tll = tl->lt; if (tll == 0) { tll = newnode; comp = 0; done = 1; } else comp = CMP(item, tll->item); if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tll; } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return Pix(root); } void SplayPQ::del(Pix pix) { SplayNode* t = (SplayNode*)pix; if (t == 0) return; SplayNode* p = t->par; --count; if (t->rt == 0) { if (t == root) { if ((root = t->lt) != 0) root->par = 0; } else if (t == p->lt) { if ((p->lt = t->lt) != 0) p->lt->par = p; } else if ((p->rt = t->lt) != 0) p->rt->par = p; } else { SplayNode* r = t->rt; SplayNode* l = r->lt; for(;;) { if (l == 0) { if (t == root) { root = r; r->par = 0; } else if (t == p->lt) { p->lt = r; r->par = p; } else { p->rt = r; r->par = p; } if ((r->lt = t->lt) != 0) r->lt->par = r; break; } else { if ((r->lt = l->rt) != 0) r->lt->par = r; l->rt = r; r->par = l; r = l; l = l->lt; } } } delete t; } & SplayPQ::front() { if (root == 0) error ("min: empty tree\n"); // else { SplayNode* t = root; SplayNode* l = root->lt; for(;;) { if (l == 0) { root = t; root->par = 0; return root->item; } else { if ((t->lt = l->rt) != 0) t->lt->par = t; l->rt = t; t->par = l; t = l; l = l->lt; } } } } void SplayPQ::del_front() { if (root != 0) { --count; SplayNode* t = root; SplayNode* l = root->lt; if (l == 0) { if ((root = t->rt) != 0) root->par = 0; delete t; } else { for(;;) { SplayNode* ll = l->lt; if (ll == 0) { if ((t->lt = l->rt) != 0) t->lt->par = t; delete l; break; } else { SplayNode* lll = ll->lt; if (lll == 0) { if ((l->lt = ll->rt) != 0) l->lt->par = l; delete ll; break; } else { t->lt = ll; ll->par = t; if ((l->lt = ll->rt) != 0) l->lt->par = l; ll->rt = l; l->par = ll; t = ll; l = lll; } } } } } } SplayPQ::deq() { if (root == 0) error("deq: empty tree"); // else { --count; SplayNode* t = root; SplayNode* l = root->lt; if (l == 0) { if ((root = t->rt) != 0) root->par = 0; res = t->item; delete t; return res; } else { for(;;) { SplayNode* ll = l->lt; if (ll == 0) { if ((t->lt = l->rt) != 0) t->lt->par = t; res = l->item; delete l; return res; } else { SplayNode* lll = ll->lt; if (lll == 0) { if ((l->lt = ll->rt) != 0) l->lt->par = l; res = ll->item; delete ll; return res; } else { t->lt = ll; ll->par = t; if ((l->lt = ll->rt) != 0) l->lt->par = l; ll->rt = l; l->par = ll; t = ll; l = lll; } } } } } } void SplayPQ::_kill(SplayNode* t) { if (t != 0) { _kill(t->lt); _kill(t->rt); delete t; } } SplayNode* SplayPQ::_copy(SplayNode* t) { if (t != 0) { SplayNode* l = _copy(t->lt); SplayNode* r = _copy(t->rt); SplayNode* x = new SplayNode(t->item, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayPQ::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } e* x = new SplayNode(t->item, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayPQ::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); Deque_h #pragma once #define _Deque_h #include #include ".defs.h" class Deque { public: Deque(); ~Deque(); virtual void push( item) = 0; // insert at front virtual void enq( item) = 0; // insert at rear virtual & front() = 0; virtual & rear() = 0; virtual deq() = 0; virtual void del_front() = 0; virtual void del_rear() = 0; virtual int empty() = 0; virtual int full() = 0; virtual int length() = 0; virtual void clear() = 0; virtual int OK() = 0; void error(const char*); }; inline Deque::Deque() {} inline Deque::~Deque() {} inline void Deque::error(const char* msg) { (*lib_error_handler)("Deque", msg); } #endif deq() = 0; virtual void del_front() = 0; virtual void del_rear() = 0; virtual ilibg++/g++-include/FPQueue.hP 644 473 0 4602 4677677733 10762 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _FPQueue_h #pragma once #define _FPQueue_h #include ".FPlex.h" #include ".Queue.h" class FPQueue : public Queue { FPlex p; public: FPQueue(int chunksize = DEFAULT_PLEX_CHUNK_SIZE); FPQueue(const FPQueue& q); ~FPQueue(); void operator = (const FPQueue&); void enq( item); deq(); & front(); void del_front(); void clear(); int empty(); int full(); int length(); int OK(); }; inline FPQueue::FPQueue(int chunksize = DEFAULT_PLEX_CHUNK_SIZE) : p(chunksize) {} inline FPQueue::FPQueue(const FPQueue& q) : p(q.p) {} inline FPQueue::~FPQueue() {} inline void FPQueue::enq(item) { p.add_high(item); } inline FPQueue::deq() { res = p.low_element(); p.del_low(); return res; } inline & FPQueue::front() { return p.low_element(); } inline void FPQueue::del_front() { p.del_low(); } inline void FPQueue::operator =(const FPQueue& s) { p = s.p; } inline int FPQueue::empty() { return p.empty(); } inline int FPQueue::full() { return p.full(); } inline int FPQueue::length() { return p.length(); } inline int FPQueue::OK() { return p.OK(); } inline void FPQueue::clear() { p.clear(); } #endif w_element(); p.del_low(); return res; } inline & FPQueue::front() { return p.low_element(); } inline void FPlibg++/g++-include/FPStack.hP 644 473 0 4613 4677677733 10745 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _FPStack_h #pragma once #define _FPStack_h #include ".FPlex.h" #include ".Stack.h" class FPStack : public Stack { FPlex p; public: FPStack(int chunksize = DEFAULT_PLEX_CHUNK_SIZE); FPStack(const FPStack& s); ~FPStack(); void operator = (const FPStack&); void push( item); pop(); & top(); void del_top(); int empty(); int full(); int length(); void clear(); int OK(); }; inline FPStack::FPStack(int chunksize = DEFAULT_PLEX_CHUNK_SIZE) : p(chunksize) {} inline FPStack::FPStack(const FPStack& s) : p(s.p) {} inline FPStack::~FPStack() {} inline void FPStack::push(item) { p.add_high(item); } inline FPStack::pop() { res = p.high_element(); p.del_high(); return res; } inline & FPStack::top() { return p.high_element(); } inline void FPStack::del_top() { p.del_high(); } inline void FPStack::operator =(const FPStack& s) { p = s.p; } inline int FPStack::empty() { return p.empty(); } inline int FPStack::full() { return p.full(); } inline int FPStack::length() { return p.length(); } inline int FPStack::OK() { return p.OK(); } inline void FPStack::clear() { p.clear(); } #endif ement(); p.del_high(); return res; } inline & FPStack::top() { return p.high_element(); } inline void .FPlex.h" FPlex:: FPlex() { lo = fnc = 0; csize = DEFAULT_INITIAL_CAPACITY; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, csize); } FPlex:: FPlex(int maxsize) { if (maxsize == 0) error("invalid constructor specification"); lo = fnc = 0; if (maxsize > 0) { csize = maxsize; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, csize); } else { csize = -maxsize; * data = new [csize]; hd = new IChunk(data, maxsize, lo, fnc, fnc); } } FPlex:: FPlex(int l, int maxsize) { if (maxsize == 0) error("invalid constructor specification"); lo = fnc = l; if (maxsize > 0) { csize = maxsize; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, csize+lo); } else { csize = -maxsize; * data = new [csize]; hd = new IChunk(data, maxsize+lo, lo, fnc, fnc); } } FPlex:: FPlex(int l, int hi, const initval, int maxsize = 0) { lo = l; fnc = hi + 1; if (maxsize >= 0) { csize = maxsize; if (csize < fnc - lo) csize = fnc - lo; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, csize); } else { csize = -maxsize; if (csize < fnc - lo) csize = fnc - lo; * data = new [csize]; hd = new IChunk(data, -csize, lo, fnc, fnc); } fill(initval); } FPlex::FPlex(const FPlex& a) { lo = a.lo; fnc = a.fnc; csize = fnc - lo; if (csize < a.csize) csize = a.csize; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, lo+csize); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } void FPlex::operator= (const FPlex& a) { if (&a != this) { del_chunk(hd); lo = a.lo; fnc = a.fnc; csize = fnc - lo; if (csize < a.csize) csize = a.csize; * data = new [csize]; hd = new IChunk(data, lo, lo, fnc, lo+csize); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } } void FPlex::append (const FPlex& a) { for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); } void FPlex::prepend (const FPlex& a) { for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); } void FPlex::reverse() { tmp; int l = lo; int h = fnc - 1; while (l < h) { tmp = (*this)[l]; (*this)[l] = (*this)[h]; (*this)[h] = tmp; next(l); prev(h); } } void FPlex::fill(const x) { for (int i = lo; i < fnc; ++i) (*this)[i] = x; } void FPlex::fill(const x, int lo, int hi) { for (int i = lo; i <= hi; ++i) (*this)[i] = x; } void FPlex::clear() { if (fnc != lo) { hd->clear(lo); fnc = lo; } } int FPlex::OK () const { int v = hd != 0; // hd exists v &= hd->IChunk::OK(); // and is OK v &= fnc - lo <= hd->size(); // and has enough space v &= lo <= fnc; // plex indices consistent v &= lo == hd->low_index(); // and match those v &= fnc == hd->fence_index(); // of chunk v &= one_chunk(); // and only one chunk if (!v) error("invariant failure"); return v; } clear(lo); fnc = lo; } } int FPlex::OK () const { int v = hd != 0; // hd exists v &= hd->IChunk::OK(); // and is OK v &= fnc - lo <= hd->size(); // and has enough space v &= lo <= fnc; // plex indices consistent v &= lo == hd->low_index(); // and match those v &= fnc == hd->fence_index(); /libg++/g++-include/FPlex.hP 644 473 0 14116 4677677734 10510 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _FPlex_h #pragma once #define _FPlex_h 1 #include ".Plex.h" class FPlex : public Plex { public: FPlex(); // set low = 0; // fence = 0; // csize = default FPlex(int maxsize); // low = 0; // fence = 0; // csize = maxsize FPlex(int lo, // low = lo; int maxsize); // fence=lo // csize = maxsize FPlex(int lo, // low = lo int hi, // fence = hi+1 const initval,// fill with initval, int maxsize = 0); // csize = maxsize // or fence - lo if 0 FPlex(const FPlex&); // X(X&) ~FPlex(); void operator= (const FPlex&); // virtuals & high_element (); & low_element (); const & high_element () const; const & low_element () const; Pix first() const; Pix last() const; void prev(Pix& ptr) const; void next(Pix& ptr) const; int owns(Pix p) const; & operator () (Pix p); const & operator () (Pix p) const; int low() const; int high() const; int valid(int idx) const; void prev(int& idx) const; void next(int& x) const; & operator [] (int index); const & operator [] (int index) const; int Pix_to_index(Pix p) const; Pix index_to_Pix(int idx) const; int can_add_high() const; int can_add_low() const; int full() const; int add_high(const elem); int del_high (); int add_low (const elem); int del_low (); void fill(const x); void fill(const x, int from, int to); void clear(); void reverse(); void append(const FPlex& a); void prepend(const FPlex& a); int OK () const; }; inline int FPlex::valid (int idx) const { return idx >= lo && idx < fnc; } inline int FPlex::low() const { return lo; } inline int FPlex::high() const { return fnc - 1; } inline Pix FPlex::first() const { return (Pix)(hd->IChunk::first_pointer()); } inline void FPlex::prev(Pix& p) const { p = Pix(hd->IChunk::pred((*) p)); } inline void FPlex::next(Pix& p) const { p = Pix(hd->IChunk::succ((*) p)); } inline Pix FPlex::last() const { return Pix(hd->IChunk::last_pointer()); } inline int FPlex::full () const { return fnc - lo == csize; } inline void FPlex::prev(int& idx) const { --idx; } inline void FPlex::next(int& idx) const { ++idx; } inline & FPlex:: operator [] (int idx) { if (idx < lo || idx >= fnc) index_error(); return *(hd->pointer_to(idx)); } inline & FPlex:: operator () (Pix p) { return *((*)p); } inline & FPlex::low_element () { if (empty()) index_error(); return *(hd->pointer_to(lo)); } inline & FPlex::high_element () { if (empty()) index_error(); return *(hd->pointer_to(fnc - 1)); } inline const & FPlex:: operator [] (int idx) const { if (idx < lo || idx >= fnc) index_error(); return *(hd->pointer_to(idx)); } inline const & FPlex:: operator () (Pix p) const { return *((const *)p); } inline const & FPlex::low_element () const { if (empty()) index_error(); return *(hd->pointer_to(lo)); } inline const & FPlex::high_element () const { if (empty()) index_error(); return *(hd->pointer_to(fnc - 1)); } inline int FPlex::can_add_high() const { return hd->can_grow_high(); } inline int FPlex::can_add_low() const { return hd->can_grow_low(); } inline int FPlex::add_high(const elem) { if (!can_add_high()) full_error(); *((hd->IChunk::grow_high())) = elem; return fnc++; } inline int FPlex::del_high () { if (empty()) empty_error(); hd->IChunk::shrink_high(); return --fnc - 1; } inline int FPlex::add_low (const elem) { if (!can_add_low()) full_error(); *((hd->IChunk::grow_low())) = elem; return --lo; } inline int FPlex::del_low () { if (empty()) empty_error(); hd->IChunk::shrink_low(); return ++lo; } inline int FPlex::owns (Pix p) const { return hd->actual_pointer(p); } inline int FPlex::Pix_to_index(Pix p) const { if (!hd->actual_pointer((const *)p)) index_error(); return hd->index_of((const *)p); } inline Pix FPlex::index_to_Pix(int idx) const { if (idx < lo || idx >= fnc) index_error(); return Pix(hd->pointer_to(idx)); } inline FPlex::~FPlex() {} #endif ine int FPlex::del_low () { if (empty()) empty_error(); hd->IChunk::shrink_low(); return ++lo; } inline int FPlex::owns (Pix p) const { return hd->actual_pointer(p); } inline int FPlex::Pix_to_index(Pix p) const { if (!hd->actual_pointer((const *)p)) index_error(); return hd->index_of((const *)p); } inline Pix FPlex::index_to_Pix(int idx) const { if (idx < lo || idx >= fnc) index_error(); libg++/g++-include/List.ccP 644 473 0 37767 4677677734 10564 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".List.h" ListNode NilListNode; class init_NilListNode { public: inline init_NilListNode() { NilListNode.tl = &NilListNode; NilListNode.ref = -1; } }; static init_NilListNode NilListNode_initializer; int operator == (List& x, List& y) { ListNode* a = x.P; ListNode* b = y.P; for (;;) { if (a == &NilListNode) return b == &NilListNode; else if (b == &NilListNode) return 0; else if (a->hd == b->hd) { a = a->tl; b = b->tl; } else return 0; } } void List::apply(Procedure f) { for(ListNode* p = P; p != &NilListNode; p = p->tl) (*f)((p->hd)); } void List::subst( old, repl) { for(ListNode* p = P; p != &NilListNode; p = p->tl) if (p->hd == old) p->hd = repl; } List::reduce(Combiner f, base) { r = base; for(ListNode* p = P; p != &NilListNode; p = p->tl) r = (*f)(r, (p->hd)); return r; } int List::position( targ) { int l = 0; ListNode* p = P; for (;;) { if (p == &NilListNode) return -1; else if (p->hd == targ) return l; else { ++l; p = p->tl; } } } int List::contains( targ) { ListNode* p = P; for (;;) { if (p == &NilListNode) return 0; else if (p->hd == targ) return 1; else p = p->tl; } } List List::find( targ) { for (ListNode* p = P; p != &NilListNode && !(p->hd == targ); p=p->tl); reference(p); return List(p); } Pix List::seek( targ) { ListNode* p = P; for (;;) { if (p == &NilListNode) return 0; else if (p->hd == targ) return Pix(p); else p = p->tl; } } int List::owns(Pix i) { ListNode* p = P; for (;;) { if (p == &NilListNode) return 0; else if (Pix(p) == i) return 1; else p = p->tl; } } List List::find(List& target) { ListNode* targ = target.P; if (targ == &NilListNode) return List(targ); ListNode* p = P; while (p != &NilListNode) { if (p->hd == targ->hd) { ListNode* a = p->tl; ListNode* t = targ->tl; for(;;) { if (t == &NilListNode) { reference(p); return List(p); } else if (a == &NilListNode || !(a->hd == t->hd)) break; else { a = a->tl; t = t->tl; } } } p = p->tl; } return List(&NilListNode); } int List::contains(List& target) { ListNode* targ = target.P; if (targ == &NilListNode) return 0; ListNode* p = P; while (p != &NilListNode) { if (p->hd == targ->hd) { ListNode* a = p->tl; ListNode* t = targ->tl; for(;;) { if (t == &NilListNode) return 1; else if (a == &NilListNode || !(a->hd == t->hd)) break; else { a = a->tl; t = t->tl; } } } p = p->tl; } return 0; } void List::del( targ) { ListNode* h = P; for (;;) { if (h == &NilListNode) { P = h; return; } else if (h->hd == targ) { ListNode* nxt = h->tl; reference(nxt); dereference(h); h = nxt; } else break; } ListNode* trail = h; ListNode* p = h->tl; while (p != &NilListNode) { if (p->hd == targ) { ListNode* nxt = p->tl; reference(nxt); dereference(p); trail->tl = nxt; p = nxt; } else { trail = p; p = p->tl; } } P = h; } void List::del(Predicate f) { ListNode* h = P; for (;;) { if (h == &NilListNode) { P = h; return; } else if ((*f)(h->hd)) { ListNode* nxt = h->tl; reference(nxt); dereference(h); h = nxt; } else break; } ListNode* trail = h; ListNode* p = h->tl; while (p != &NilListNode) { if ((*f)(p->hd)) { ListNode* nxt = p->tl; reference(nxt); dereference(p); trail->tl = nxt; p = nxt; } else { trail = p; p = p->tl; } } P = h; } void List::select(Predicate f) { ListNode* h = P; for (;;) { if (h == &NilListNode) { P = h; return; } else if (!(*f)(h->hd)) { ListNode* nxt = h->tl; reference(nxt); dereference(h); h = nxt; } else break; } ListNode* trail = h; ListNode* p = h->tl; while (p != &NilListNode) { if (!(*f)(p->hd)) { ListNode* nxt = p->tl; reference(nxt); dereference(p); trail->tl = nxt; p = nxt; } else { trail = p; p = p->tl; } } P = h; } void List::reverse() { ListNode* l = &NilListNode; ListNode* p = P; while (p != &NilListNode) { ListNode* nxt = p->tl; p->tl = l; l = p; p = nxt; } P = l; } List copy(List& x) { ListNode* a = x.P; if (a == &NilListNode) return List(a); else { ListNode* h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; } trail->tl = &NilListNode; return List(h); } } List subst( old, repl, List& x) { ListNode* a = x.P; if (a == &NilListNode) return List(a); else { ListNode* h = new ListNode; h->ref = 1; if (a->hd == old) h->hd = repl; else h->hd = a->hd; ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = new ListNode; n->ref = 1; if (a->hd == old) n->hd = repl; else n->hd = a->hd; trail->tl = n; trail = n; } trail->tl = &NilListNode; return List(h); } } List combine(Combiner f, List& x, List& y) { ListNode* a = x.P; ListNode* b = y.P; if (a == &NilListNode || b == &NilListNode) return List(&NilListNode); else { ListNode* h = newListNode((*f)(a->hd, b->hd)); ListNode* trail = h; a = a->tl; b = b->tl; while (a != &NilListNode && b != &NilListNode) { ListNode* n = newListNode((*f)(a->hd, b->hd)); trail->tl = n; trail = n; a = a->tl; b = b->tl; } trail->tl = &NilListNode; return List(h); } } List reverse(List& x) { ListNode* a = x.P; if (a == &NilListNode) return List(a); else { ListNode* l = newListNode(a->hd); l->tl = &NilListNode; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = newListNode(a->hd); n->tl = l; l = n; } return List(l); } } List append(List& x, List& y) { ListNode* a = x.P; ListNode* b = y.P; reference(b); if (a != &NilListNode) { ListNode* h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; } trail->tl = b; return List(h); } else return List(b); } void List::prepend(List& y) { ListNode* b = y.P; if (b != &NilListNode) { ListNode* h = newListNode(b->hd); ListNode* trail = h; for(b = b->tl; b != &NilListNode; b = b->tl) { ListNode* n = newListNode(b->hd); trail->tl = n; trail = n; } trail->tl = P; P = h; } } List concat(List& x, List& y) { ListNode* a = x.P; ListNode* b = y.P; if (a != &NilListNode) { ListNode* h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; }; for(;b != &NilListNode; b = b->tl) { ListNode* n = newListNode(b->hd); trail->tl = n; trail = n; } trail->tl = &NilListNode; return List(h); } else if (b != &NilListNode) { ListNode* h = newListNode(b->hd); ListNode* trail = h; for(b = b->tl; b != &NilListNode; b = b->tl) { ListNode* n = newListNode(b->hd); trail->tl = n; trail = n; } trail->tl = &NilListNode; return List(h); } else return List(&NilListNode); } List select(Predicate f, List& x) { ListNode* a = x.P; ListNode* h = &NilListNode; while (a != &NilListNode) { if ((*f)(a->hd)) { h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { if ((*f)(a->hd)) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; } } trail->tl = &NilListNode; break; } else a = a->tl; } return List(h); } List remove(Predicate f, List& x) { ListNode* a = x.P; ListNode* h = &NilListNode; while (a != &NilListNode) { if (!(*f)(a->hd)) { h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { if (!(*f)(a->hd)) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; } } trail->tl = &NilListNode; break; } else a = a->tl; } return List(h); } List remove( targ, List& x) { ListNode* a = x.P; ListNode* h = &NilListNode; while (a != &NilListNode) { if (!(a->hd == targ)) { h = newListNode(a->hd); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { if (!(a->hd == targ)) { ListNode* n = newListNode(a->hd); trail->tl = n; trail = n; } } trail->tl = &NilListNode; break; } else a = a->tl; } return List(h); } List map(Mapper f, List& x) { ListNode* a = x.P; ListNode* h = &NilListNode; if (a != &NilListNode) { h = newListNode((*f)(a->hd)); ListNode* trail = h; for(a = a->tl; a != &NilListNode; a = a->tl) { ListNode* n = newListNode((*f)(a->hd)); trail->tl = n; trail = n; } trail->tl = &NilListNode; } return List(h); } List merge(List& x, List& y, Comparator f) { ListNode* a = x.P; ListNode* b = y.P; if (a == &NilListNode) { if (b == &NilListNode) return List(&NilListNode); else return copy(y); } else if (b == &NilListNode) return copy(x); ListNode* h = new ListNode; h->ref = 1; if ((*f)(a->hd, b->hd) <= 0) { h->hd = a->hd; a = a->tl; } else { h->hd = b->hd; b = b->tl; } ListNode* r = h; for(;;) { if (a == &NilListNode) { while (b != &NilListNode) { ListNode* n = new ListNode; n->ref = 1; n->hd = b->hd; r->tl = n; r = n; b = b->tl; } r->tl = &NilListNode; return List(h); } else if (b == &NilListNode) { while (a != &NilListNode) { ListNode* n = new ListNode; n->ref = 1; n->hd = a->hd; r->tl = n; r = n; a = a->tl; } r->tl = &NilListNode; return List(h); } else if ((*f)(a->hd, b->hd) <= 0) { ListNode* n = new ListNode; n->ref = 1; n->hd = a->hd; r->tl = n; r = n; a = a->tl; } else { ListNode* n = new ListNode; n->ref = 1; n->hd = b->hd; r->tl = n; r = n; b = b->tl; } } } void List::sort(Comparator f) { // strategy: place runs in queue, merge runs until done // This is often very fast if (P == &NilListNode || P->tl == &NilListNode) return; int qlen = 250; // guess a good queue size, realloc if necessary ListNode** queue = (ListNode**)malloc(qlen * sizeof(ListNode*)); ListNode* h = P; ListNode* a = h; ListNode* b = a->tl; int qin = 0; while (b != &NilListNode) { if ((*f)(a->hd, b->hd) > 0) { if (h == a) // minor optimization: ensure runlen >= 2 { h = b; a->tl = b->tl; b->tl = a; b = a->tl; } else { if (qin >= qlen) { qlen *= 2; queue = (ListNode**)realloc(queue, qlen * sizeof(ListNode*)); } queue[qin++] = h; a->tl = &NilListNode; h = a = b; b = b->tl; } } else { a = b; b = b->tl; } } int count = qin; queue[qin] = h; if (++qin >= qlen) qin = 0; int qout = 0; while (count-- > 0) { a = queue[qout]; if (++qout >= qlen) qout = 0; b = queue[qout]; if (++qout >= qlen) qout = 0; if ((*f)(a->hd, b->hd) <= 0) { h = a; a = a->tl; } else { h = b; b = b->tl; } queue[qin] = h; if (++qin >= qlen) qin = 0; for (;;) { if (a == &NilListNode) { h->tl = b; break; } else if (b == &NilListNode) { h->tl = a; break; } else if ((*f)(a->hd, b->hd) <= 0) { h->tl = a; h = a; a = a->tl; } else { h->tl = b; h = b; b = b->tl; } } } P = queue[qout]; free(queue); } int List::list_length() { ListNode* fast = P; if (fast == &NilListNode) return 0; ListNode* slow = fast->tl; if (slow == &NilListNode) return 1; fast = slow->tl; int n = 2; for (;;) { if (fast == &NilListNode) return n; else if (fast->tl == &NilListNode) return n+1; else if (fast == slow) return -1; else { n += 2; fast = fast->tl->tl; slow = slow->tl; } } } void List::error(const char* msg) { (*lib_error_handler)("List", msg); } int List::OK() { int v = P != 0; // have a node // check that all nodes OK, even if circular: ListNode* fast = P; if (fast != &NilListNode) { v &= fast->ref != 0; ListNode* slow = fast->tl; v &= slow->ref != 0; if (v && slow != &NilListNode) { fast = slow->tl; v &= fast->ref != 0; while (v) { if (fast == &NilListNode) break; else if (fast->tl == &NilListNode) break; else if (fast == slow) break; else { v &= fast->ref != 0 && slow->ref != 0; fast = fast->tl->tl; slow = slow->tl; } } } } if (!v) error ("invariant failure"); return v; } = slow->rlibg++/g++-include/Map.ccP 644 473 0 2716 4677677734 10330 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include "..Map.h" Pix Map::seek( item) { for (Pix i = first(); i != 0 && !(EQ(key(i), item)); next(i)); return i; } int Map::owns(Pix idx) { if (idx == 0) return 0; for (Pix i = first(); i; next(i)) if (i == idx) return 1; return 0; } void Map::clear() { Pix i = first(); while (i != 0) { del(key(i)); i = first(); } } int Map::contains ( item) { return seek(item) != 0; } void Map::error(const char* msg) { (*lib_error_handler)("Set", msg); } Map.h" Pix Map::seek( item) { for (Plibg++/g++-include/MPlex.ccP 644 473 0 40353 4677677735 10660 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".MPlex.h" // MChunk support MChunk::MChunk(* d, int baseidx, int lowidx, int fenceidx, int topidx) : IChunk(d, baseidx, lowidx, fenceidx, topidx) { unused = fence - low; unsigned msize = (top - base)/_MAP_BITS + 1; map = (unsigned long *) (new long[msize]); bzero((void*)map, msize * sizeof(long)); } void MChunk:: shrink_high () { if (fence <= low) empty_error(); --fence; if (!valid(fence)) --unused; else free(fence); reset_high(); } void MChunk:: shrink_low () { if (fence <= low) empty_error(); if (!valid(low)) --unused; else free(low); ++low; reset_low(); } void MChunk::clear(int lo) { int s = top - base; low = base = fence = lo; top = base + s; unused = 0; bzero((void*)map, ((top - base)/_MAP_BITS + 1) * sizeof(long)); } void MChunk::cleardown(int hi) { int s = top - base; low = top = fence = hi; base = top - s; unused = 0; bzero((void*)map, ((top - base)/_MAP_BITS + 1) * sizeof(long)); } int MChunk::del(int idx) { if (idx < low || idx >= fence) index_error(); int v = valid(idx); if (v) { free(idx); ++unused; } return v; } int MChunk::undel(int idx) { if (idx < low || idx >= fence) index_error(); int v = valid(idx); if (!v) { mark(idx); --unused; } return v; } int MChunk::unused_index() const { if (unused_indices() == 0) index_error(); int slot; if (low == base) // can traverse 32 slots at a time { int blk = 0; while (map[blk] == ~0L) ++blk; slot = blk * _MAP_BITS + base; } else slot = low; while(valid(slot)) ++slot; return slot; } int MChunk::first_index() const { if (empty()) return fence; int slot; if (low == base) { int blk = 0; while (map[blk] == 0) ++blk; slot = blk * _MAP_BITS + base; } else slot = low; while(!valid(slot)) ++slot; return slot; } int MChunk::last_index() const { if (empty()) return low - 1; int slot; if (top == fence) { int blk = (top - base) / _MAP_BITS; while (map[blk] == 0) --blk; slot = blk * _MAP_BITS + base + _MAP_BITS - 1; } else slot = fence - 1; while(!valid(slot)) --slot; return slot; } int MChunk:: OK() const { int v = data != 0; // have some data v &= map != 0; // and a map v &= base <= low; // ok, index-wise v &= low <= fence; v &= fence <= top; v &= nxt->prev() == this; // and links are OK v &= prv->next() == this; int bitcount = 0; // and unused count correct for (int i = low; i < fence; ++i) if (!valid(i)) ++bitcount; v &= unused == bitcount; if (!v) error("invariant failure"); return(v); } * MChunk::succ(* p) const { int i = ((int) p - (int) data) / sizeof() + base + 1; if (p == 0 || i < low) return 0; while (i < fence && !valid(i)) ++i; if (i >= fence) return 0; return pointer_to(i); } * MChunk::pred(* p) const { int i = ((int) p - (int) data) / sizeof() + base - 1; if (p == 0 || i >= fence) return 0; while (i >= low && !valid(i)) --i; if (i < low) return 0; return pointer_to(i); } * MChunk::first_pointer() const { if (empty()) return 0; int slot; if (low == base) { int blk = 0; while (map[blk] == 0) ++blk; slot = blk * _MAP_BITS + base; } else slot = low; while(!valid(slot)) ++slot; return pointer_to(slot); } * MChunk::last_pointer() const { if (empty()) return 0; int slot; if (top == fence) { int blk = (top - base) / _MAP_BITS; while (map[blk] == 0) --blk; slot = blk * _MAP_BITS + base + _MAP_BITS - 1; } else slot = fence - 1; while(!valid(slot)) --slot; return pointer_to(slot); } MPlex:: MPlex() { unused = 0; lo = fnc = 0; csize = DEFAULT_INITIAL_CAPACITY; * data = new [csize]; hd = ch = new MChunk(data, lo, lo, fnc, lo+csize); } MPlex:: MPlex(int chunksize) { if (chunksize == 0) error("invalid constructor specification"); unused = 0; lo = fnc = 0; if (chunksize > 0) { csize = chunksize; * data = new [csize]; hd = ch = new MChunk(data, lo, lo, fnc, csize); } else { csize = -chunksize; * data = new [csize]; hd = ch = new MChunk(data, chunksize, lo, fnc, fnc); } } MPlex:: MPlex(int l, int chunksize) { if (chunksize == 0) error("invalid constructor specification"); unused = 0; lo = fnc = l; if (chunksize > 0) { csize = chunksize; * data = new [csize]; hd = ch = new MChunk(data, lo, lo, fnc, csize+lo); } else { csize = -chunksize; * data = new [csize]; hd = ch = new MChunk(data, chunksize+lo, lo, fnc, fnc); } } void MPlex::make_initial_chunks(int up = 1) { int need = fnc - lo; hd = 0; if (up) { int l = lo; do { int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; MChunk* h = new MChunk(data, l, l, l+sz, l+csize); if (hd != 0) h->link_to_next(hd); else hd = h; l += sz; need -= sz; } while (need > 0); } else { int hi = fnc; do { int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; MChunk* h = new MChunk(data, hi-csize, hi-sz, hi, hi); if (hd != 0) h->link_to_next(hd); hd = h; hi -= sz; need -= sz; } while (need > 0); } ch = (MChunk*) hd; } MPlex:: MPlex(int l, int hi, const initval, int chunksize = 0) { unused = 0; lo = l; fnc = hi + 1; if (chunksize == 0) { csize = fnc - l; make_initial_chunks(1); } else if (chunksize < 0) { csize = -chunksize; make_initial_chunks(0); } else { csize = chunksize; make_initial_chunks(1); } fill(initval); } MPlex::MPlex(const MPlex& a) { lo = a.lo; fnc = a.fnc; csize = a.csize; unused = fnc - lo; hd = 0; const IChunk* p = a.hd; do { * data = new [p->size()]; MChunk* h = new MChunk(data, p->base_index(), p->low_index(), p->fence_index(), p->top_index()); if (hd != 0) h->link_to_next(hd); else hd = h; p = p->next(); } while (p != a.hd); ch = (MChunk*) hd; for (int i = a.low(); i < a.fence(); a.next(i)) { undel_index(i); (*this)[i] = a[i]; } } void MPlex::operator= (const MPlex& a) { if (&a != this) { invalidate(); lo = a.lo; fnc = a.fnc; csize = a.csize; unused = fnc - lo; hd = 0; const IChunk* p = a.hd; do { * data = new [p->size()]; MChunk* h = new MChunk(data, p->base_index(), p->low_index(), p->fence_index(), p->top_index()); if (hd != 0) h->link_to_next(hd); else hd = h; p = p->next(); } while (p != a.hd); ch = (MChunk*) hd; for (int i = a.low(); i < a.fence(); a.next(i)) { undel_index(i); (*this)[i] = a[i]; } } } int MPlex::valid(int idx) const { const MChunk* tail = (MChunk*)tl(); const MChunk* t = ch; while (idx >= t->fence_index()) { if (t == tail) return 0; t = ((MChunk*)(t->next())); } while (idx < t->low_index()) { if (t == hd) return 0; t = ((MChunk*)(t->prev())); } set_cache(t); return t->MChunk::valid_index(idx); } void MPlex::cache(int idx) const { const MChunk* tail = (MChunk*)tl(); const MChunk* t = ch; while (idx >= t->fence_index()) { if (t == tail) index_error(); t = ((MChunk*)(t->next())); } while (idx < t->low_index()) { if (t == hd) index_error(); t = ((MChunk*)(t->prev())); } if (!t->MChunk::valid_index(idx)) index_error(); set_cache(t); } void MPlex::cache(const * p) const { const MChunk* old = ch; const MChunk* t = ch; while (!t->actual_pointer(p)) { t = ((MChunk*)(t->next())); if (t == old) index_error(); } if (!t->MChunk::valid_pointer(p)) index_error(); set_cache(t); } int MPlex::owns(Pix p) const { const MChunk* old = ch; const MChunk* t = ch; while (!t->actual_pointer(p)) { t = ((MChunk*)(t->next())); if (t == old) return 0; } set_cache(t); return t->MChunk::valid_pointer(p); } int MPlex::add_high(const elem) { MChunk* t = ((MChunk*) tl()); if (!t->can_grow_high()) { * data = new [csize]; t = (new MChunk(data, fnc,fnc,fnc,fnc+csize)); t->link_to_prev(tl()); } *((t->MChunk::grow_high())) = elem; set_cache(t); return fnc++; } int MPlex::add_low (const elem) { MChunk* t = ((MChunk*) hd); if (!t->can_grow_low()) { * data = new [csize]; hd = new MChunk(data, lo-csize, lo, lo, lo); hd->link_to_next(t); t = ((MChunk*) hd); } *((t->MChunk::grow_low())) = elem; set_cache(t); return --lo; } void MPlex::adjust_bounds() { MChunk* t = ((MChunk*) tl()); while (t->MChunk::empty() && !one_chunk()) { MChunk* pred = (MChunk*)(t->prev()); del_chunk(t); pred->reset_high(); t = (pred); } int oldfnc = fnc; fnc = t->fence_index(); unused -= oldfnc - fnc - 1; t = ((MChunk*) hd); while (t->MChunk::empty() && !one_chunk()) { hd = (MChunk*)(t->next()); del_chunk(t); t = ((MChunk*) hd); t->reset_low(); } int oldlo = lo; lo = t->low_index(); unused -= lo - oldlo - 1; set_cache(t); } int MPlex::del_high () { if (empty()) empty_error(); MChunk* t = ((MChunk*) tl()); while (t->MChunk::empty() && !one_chunk()) // possible stragglers { MChunk* pred = (MChunk*)(t->prev()); del_chunk(t); pred->reset_high(); t = (pred); } t->MChunk::shrink_high(); while (t->MChunk::empty() && !one_chunk()) { MChunk* pred = (MChunk*)(t->prev()); del_chunk(t); pred->reset_high(); t = (pred); } int oldfnc = fnc; fnc = t->fence_index(); unused -= oldfnc - fnc - 1; set_cache(t); return fnc - 1; } int MPlex::del_low () { if (empty()) empty_error(); MChunk* t = ((MChunk*) hd); while (t->MChunk::empty() && !one_chunk()) { hd = (MChunk*)(t->next()); del_chunk(t); t = ((MChunk*) hd); t->reset_low(); } t->MChunk::shrink_low(); while (t->MChunk::empty() && !one_chunk()) { hd = (MChunk*)(t->next()); del_chunk(t); t = ((MChunk*) hd); t->reset_low(); } int oldlo = lo; lo = t->low_index(); unused -= lo - oldlo - 1; set_cache(t); return lo; } int MPlex::add(const elem) { if (unused == 0) return add_high(elem); for(MChunk* t = ch; t->unused_indices() == 0; t = (MChunk*)(t->prev())) ; int i = t->unused_index(); set_cache(t); undel_index(i); (*this)[i] = elem; return i; } int MPlex::unused_index() const { if (unused == 0) index_error(); for(MChunk* t = ch; t->unused_indices() == 0; t = (MChunk*)(t->prev())) ; set_cache(t); return t->unused_index(); } Pix MPlex::unused_Pix() const { if (unused == 0) return 0; for(MChunk* t = ch; t->unused_indices() == 0; t = (MChunk*)(t->prev())) ; set_cache(t); return t->pointer_to(t->unused_index()); } int MPlex::del_index(int idx) { if (idx < lo || idx >= fnc) index_error(); if (MPlex::valid(idx)) { ++unused; ch->MChunk::del(idx); return 1; } else return 0; } int MPlex::dopred(int idx) const { if (idx >= fnc) idx = fnc; if (idx <= lo) return lo - 1; const MChunk* t = ch; while (idx > t->fence_index()) { t = ((MChunk*)(t->next())); } while (idx <= t->low_index()) { t = ((MChunk*)(t->prev())); } int i = t->MChunk::pred(idx); while (i < t->low_index() && i >= lo) { t = ((MChunk*)(t->prev())); i = t->MChunk::last_index(); } set_cache(t); return i; } int MPlex::dosucc(int idx) const { if (idx < lo) idx = lo; if (idx >= fnc - 1) return fnc; const MChunk* t = ch; while (idx >= t->fence_index()) { t = ((MChunk*)(t->next())); } while (idx < t->low_index()) { t = ((MChunk*)(t->prev())); } int i = t->MChunk::succ(idx); while (i >= t->fence_index() && i < fnc) { t = (MChunk*)(t->next()); i = t->MChunk::first_index(); } set_cache(t); return i; } void MPlex::prev(Pix& i) const { if (i == 0) return; * p = (*) i; const MChunk* old = ch; const MChunk* t = ch; while (!t->actual_pointer(p)) { t = ((MChunk*)(t->prev())); if (t == old) { i = 0; return; } } * q = t->MChunk::pred(p); while (q == 0 && t != hd) { t = ((MChunk*)(t->prev())); q = t->MChunk::last_pointer(); } i = Pix(q); set_cache(t); return; } void MPlex::next(Pix& i) const { if (i == 0) return; * p = (*) i; const MChunk* tail = (MChunk*)(tl()); const MChunk* old = ch; const MChunk* t = ch; while (!t->actual_pointer(p)) { t = ((MChunk*)(t->next())); if (t == old) { i = 0; return; } } * q = t->MChunk::succ(p); while (q == 0 && t != tail) { t = ((MChunk*)(t->next())); q = t->MChunk::first_pointer(); } i = Pix(q); set_cache(t); return; } void MPlex::undel_index(int idx) { if (idx < lo || idx >= fnc) index_error(); const MChunk* t = ch; while (idx >= t->fence_index()) { t = ((MChunk*)(t->next())); } while (idx < t->low_index()) { t = ((MChunk*)(t->prev())); } int was_present = t->MChunk::undel(idx); if (!was_present) { --unused; } set_cache(t); return; } void MPlex::clear() { if (fnc != lo) { MChunk* t = ((MChunk*)tl()); while (t != hd) { MChunk* prv = (MChunk*)(t->prev()); del_chunk(t); t = prv; } t->MChunk::clear(lo); set_cache(t); fnc = lo; unused = 0; } } int MPlex::OK () const { int v = hd != 0; // at least one chunk int found_ch = 0; // to make sure ch is in list; int count = 0; // to count unused slots const MChunk* t = (MChunk*)(hd); int gap = t->low_index() - lo; v &= gap == 0; // hd lo not less than lo. count += gap; for (;;) { if (t == ch) ++found_ch; v &= t->MChunk::OK(); // each chunk is OK count += t->unused_indices(); if (t == tl()) break; else // and has indices less than succ { gap = t->next()->base_index() - t->top_index(); v &= gap == 0; count += gap; if (t != hd) // internal chunks can't grow v &= !t->can_grow_low() && !t->can_grow_high(); t = (const MChunk*)(t->next()); } } gap = fnc - t->fence_index(); v &= gap == 0; count += gap; v &= count == unused; // chunk counts agree with plex v &= found_ch == 1; if (!v) error("invariant failure"); return v; } s indices less than succ { gap = t->next()->base_index() - t->top_index(); v &= gap == 0; count += gap; if (t != hd) // internal chunks can't grow v &= !t->can_grow_low() && !t->can_grow_high(); t = (const MChunk*libg++/g++-include/MPlex.hP 644 473 0 25701 4677677735 10522 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _MPlex_h #pragma once #define _MPlex_h 1 #include ".Plex.h" // Number of bits per long, used in MChunk bit map operations #define _MAP_BITS 32 class MChunk : public IChunk { protected: unsigned long* map; // bitmap of slots int unused; // number of unused internal slots void mark(int); // bitmap operations void free(int); int valid(int) const; public: MChunk(* d, // ptr to array of elements int base_idx, // initial indices int low_idx, // & initially clear map int fence_idx, int top_idx); ~MChunk(); // virtuals int first_index() const; int last_index() const; int succ(int idx) const; int pred(int idx) const; * first_pointer() const; * last_pointer() const; * succ(*) const; * pred(*) const; int empty() const; int full() const; int valid_index(int i) const; int valid_pointer(const * p) const; * grow_high (); * grow_low (); void shrink_high (); void shrink_low (); void clear(int); void cleardown(int); int OK() const; // extensions int unused_indices() const; // how many free slot in low..fence? int unused_index() const; // return index of free slot int del(int i); // delete data indexed by i // return true if was present int undel(int idx); // un-delete data indexed by i // return true if already present void reset_low(); // reset low = lowest valid index; void reset_high(); // same for high }; class MPlex: public Plex { MChunk* ch; // cached chunk int unused; // # of free slots between low & fence void make_initial_chunks(int up = 1); void cache(int idx) const; void cache(const * p) const; int dopred(int) const; int dosucc(int) const; void set_cache(const MChunk* t) const; // logically, // not physically const public: MPlex(); // set low = 0; // fence = 0; // csize = default MPlex(int ch_size); // low = 0; // fence = 0; // csize = ch_size MPlex(int lo, // low = lo; int ch_size); // fence=lo // csize = ch_size MPlex(int lo, // low = lo int hi, // fence = hi+1 const initval,// fill with initval, int ch_size = 0); // csize= ch_size // or fence-lo if 0 MPlex(const MPlex&); void operator= (const MPlex&); // virtuals & high_element (); & low_element (); const & high_element () const; const & low_element () const; Pix first() const; Pix last() const ; void prev(Pix& ptr) const; void next(Pix& ptr) const; int owns(Pix p) const; & operator () (Pix p); const & operator () (Pix p) const; int low() const; int high() const; int valid(int idx) const; void prev(int& idx) const; void next(int& x) const; & operator [] (int index); const & operator [] (int index) const; int Pix_to_index(Pix p) const; Pix index_to_Pix(int idx) const; int can_add_high() const; int can_add_low() const; int full() const; int add_high(const elem); int del_high (); int add_low (const elem); int del_low (); void clear(); int OK () const; // extensions int count() const; // # valid elements int available() const; // # deleted elements int unused_index()const; // return index of a deleted elem Pix unused_Pix() const; // return Pix of a deleted elem int del_index(int idx); // logically delete at idx; // return true if was present int del_Pix(Pix p); // delete at p void undel_index(int idx); // undelete at idx; void undel_Pix(Pix p); // undelete at p; void adjust_bounds(); // reset lo, hi to lowest & // highest valid indices int add(const elem); // add anywhere }; inline MChunk:: ~MChunk() { delete map; } inline void MChunk::mark(int idx) { unsigned int i = idx - base; map[i / _MAP_BITS] |= 1 << (i & (_MAP_BITS - 1)); } inline void MChunk::free(int idx) { unsigned int i = idx - base; map[i / _MAP_BITS] &= ~(1 << (i & (_MAP_BITS - 1))); } inline int MChunk::valid(int idx) const { unsigned int i = idx - base; return map[i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1))); } inline int MChunk:: valid_index(int i) const { return i >= low && i < fence && valid(i); } inline int MChunk:: valid_pointer(const * p) const { int i = ((int)p - (int)data) / sizeof(); return i >= 0 && i < (fence - base) && (map[(unsigned)i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1)))); } inline int MChunk::empty() const { return fence - low - unused == 0; } inline int MChunk::full() const { return unused + (top - fence) + (low - base) == 0; } inline int MChunk::succ(int idx) const { int i = (idx < low)? low : idx + 1; while (i < fence && !valid(i)) ++i; return i; } inline int MChunk::pred(int idx) const { int i = (idx > fence)? (fence - 1) : idx - 1; while (i >= low && !valid(i)) --i; return i; } inline int MChunk::unused_indices() const { return unused; } inline * MChunk:: grow_high () { if (!can_grow_high()) full_error(); mark(fence); return &(data[fence++ - base]); } inline * MChunk:: grow_low () { if (!can_grow_low()) full_error(); mark(--low); return &(data[low - base]); } inline void MChunk::reset_low() { while (low < fence && !valid(low)) { --unused; ++low; } } inline void MChunk::reset_high() { while (fence > low && !valid(fence - 1)) { --unused; --fence; } } inline int MPlex::full () const { return 0; } inline int MPlex::can_add_high() const { return 1; } inline int MPlex::can_add_low() const { return 1; } inline int MPlex::available() const { return unused; } inline int MPlex::count() const { return fnc - lo - unused; } inline void MPlex::set_cache(const MChunk* t) const { ((MPlex*)(this))->ch = t; } inline & MPlex:: operator [] (int idx) { if (!ch->MChunk::valid_index(idx)) cache(idx); return * (ch->pointer_to(idx)); } inline const & MPlex:: operator [] (int idx) const { if (!ch->MChunk::valid_index(idx)) cache(idx); return * ((const *)(ch->pointer_to(idx))); } inline int MPlex::Pix_to_index(Pix p) const { if (!ch->MChunk::valid_pointer((*)p)) cache((*)p); return ch->index_of((*)p); } inline int MPlex::high() const { return (unused == fnc - lo)? lo - 1 : (((const MChunk*)tl())->MChunk::last_index()); } inline int MPlex::low() const { return (unused == fnc - lo)? fnc : (((const MChunk*)hd)->MChunk::first_index()); } inline & MPlex::low_element () { if (unused == fnc - lo) index_error(); return *((hd->pointer_to(((MChunk*)(hd))->MChunk::first_index()))); } inline const & MPlex::low_element () const { if (unused == fnc - lo) index_error(); return *((const *)((((MChunk*)(hd))-> pointer_to(((MChunk*)(hd))-> MChunk::first_index())))); } inline & MPlex::high_element () { if (unused == fnc - lo) index_error(); return *((*)((((MChunk*)tl())-> pointer_to(((MChunk*)tl())->MChunk::last_index())))); } inline const & MPlex::high_element () const { if (unused == fnc - lo) index_error(); return *((const *)((((MChunk*)tl())->pointer_to(((MChunk*)tl())->MChunk::last_index())))); } inline Pix MPlex::index_to_Pix(int idx) const { if (!ch->MChunk::valid_index(idx)) cache(idx); return Pix(ch->pointer_to(idx)); } inline void MPlex::next(int& idx) const { idx = (ch->MChunk::valid_index(idx+1))? idx+1 : dosucc(idx); } inline void MPlex::prev(int& idx) const { idx = (ch->MChunk::valid_index(idx-1))? idx-1 : dopred(idx); } inline Pix MPlex::first() const { return Pix(((MChunk*)(hd))->MChunk::first_pointer()); } inline Pix MPlex::last() const { return Pix(((MChunk*)(tl()))->MChunk::last_pointer()); } inline void MPlex::undel_Pix(Pix p) { undel_index(Pix_to_index(p)); } inline int MPlex::del_Pix(Pix p) { return del_index(Pix_to_index(p)); } inline & MPlex:: operator () (Pix p) { return *((*)p); } inline const & MPlex:: operator () (Pix p) const { return *((const *)p); } #endif MPlex::first() const { return Pix(((MChunk*)(hd))->libg++/g++-include/Vec.ccP 644 473 0 26451 4677677735 10353 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".Vec.h" // error handling void default_Vec_error_handler(const char* msg) { cerr << "Fatal Vec error. " << msg << "\n"; exit(1); } one_arg_error_handler_t Vec_error_handler = default_Vec_error_handler; one_arg_error_handler_t set_Vec_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Vec_error_handler; Vec_error_handler = f; return old; } void Vec::error(const char* msg) { (*Vec_error_handler)(msg); } void Vec::range_error() { (*Vec_error_handler)("Index out of range."); } // can't just realloc since there may be need for constructors/destructors void Vec::resize(int newl) { * news = new [newl]; * p = news; int minl = len * top = &(s[minl]); * t = s; while (t < top) *p++ = *t++; delete [len] s; s = news; len = newl; } Vec concat(Vec & a, Vec & b) { int newl = a.len + b.len; * news = new [newl]; * p = news; * top = &(a.s[a.len]); * t = a.s; while (t < top) *p++ = *t++; top = &(b.s[b.len]); t = b.s; while (t < top) *p++ = *t++; return Vec(newl, news); } Vec combine(Combiner f, Vec& a, Vec& b) { int newl = a.len * news = new [newl]; * p = news; * top = &(a.s[newl]); * t = a.s; * u = b.s; while (t < top) *p++ = (*f)(*t++, *u++); return Vec(newl, news); } Vec::reduce(Combiner f, base) { r = base; * top = &(s[len]); * t = s; while (t < top) r = (*f)(r, *t++); return r; } Vec reverse(Vec& a) { * news = new [a.len]; if (a.len != 0) { * lo = news; * hi = &(news[a.len - 1]); while (lo < hi) { tmp = *lo; *lo++ = *hi; *hi-- = tmp; } } return Vec(a.len, news); } void Vec::reverse() { if (len != 0) { * lo = s; * hi = &(s[len - 1]); while (lo < hi) { tmp = *lo; *lo++ = *hi; *hi-- = tmp; } } } int Vec::index( targ) { for (int i = 0; i < len; ++i) if (targ == s[i]) return i; return -1; } Vec map(Mapper f, Vec& a) { * news = new [a.len]; * p = news; * top = &(a.s[a.len]); * t = a.s; while(t < top) *p++ = (*f)(*t++); return Vec(a.len, news); } int operator == (Vec& a, Vec& b) { if (a.len != b.len) return 0; * top = &(a.s[a.len]); * t = a.s; * u = b.s; while (t < top) if (*t++ != *u++) return 0; return 1; } void Vec::fill( val, int from = 0, int n = -1) { int to; if (n < 0) to = len - 1; else to = from + n - 1; if ((unsigned)from > to) range_error(); * t = &(s[from]); * top = &(s[to]); while (t <= top) *t++ = val; } Vec Vec::at(int from = 0, int n = -1) { int to; if (n < 0) { n = len - from; to = len - 1; } else to = from + n - 1; if ((unsigned)from > to) range_error(); * news = new [n]; * p = news; * t = &(s[from]); * top = &(s[to]); while (t <= top) *p++ = *t++; return Vec(n, news); } Vec merge(Vec & a, Vec & b, Comparator f) { int newl = a.len + b.len; * news = new [newl]; * p = news; * topa = &(a.s[a.len]); * as = a.s; * topb = &(b.s[b.len]); * bs = b.s; for (;;) { if (as >= topa) { while (bs < topb) *p++ = *bs++; break; } else if (bs >= topb) { while (as < topa) *p++ = *as++; break; } else if ((*f)(*as, *bs) <= 0) *p++ = *as++; else *p++ = *bs++; } return Vec(newl, news); } static int gsort(*, int, Comparator); void Vec::sort (Comparator compar) { gsort(s, len, compar); } // An adaptation og Schmidt's new quicksort static inline void SWAP(* A, * B) { tmp = *A; *A = *B; *B = tmp; } /* This should be replaced by a standard ANSI macro. */ #define BYTES_PER_WORD 8 /* The next 4 #defines implement a very fast in-line stack abstraction. */ #define STACK_SIZE (BYTES_PER_WORD * sizeof (long)) #define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0) #define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0) #define STACK_NOT_EMPTY (stack < top) /* Discontinue quicksort algorithm when partition gets below this size. This particular magic number was chosen to work best on a Sun 4/260. */ #define MAX_THRESH 4 /* Order size using quicksort. This implementation incorporates four optimizations discussed in Sedgewick: 1. Non-recursive, using an explicit stack of pointer that store the next array partition to sort. To save time, this maximum amount of space required to store an array of MAX_INT is allocated on the stack. Assuming a 32-bit integer, this needs only 32 * sizeof (stack_node) == 136 bits. Pretty cheap, actually. 2. Chose the pivot element using a median-of-three decision tree. This reduces the probability of selecting a bad pivot value and eliminates certain extraneous comparisons. 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion sort to order the MAX_THRESH items within each partition. This is a big win, since insertion sort is faster for small, mostly sorted array segements. 4. The larger of the two sub-partitions is always pushed onto the stack first, with the algorithm then concentrating on the smaller partition. This *guarantees* no more than log (n) stack size is needed! */ static int gsort ( *base_ptr, int total_elems, Comparator cmp) { /* Stack node declarations used to store unfulfilled partition obligations. */ struct stack_node { *lo; *hi; }; pivot_buffer; int max_thresh = MAX_THRESH; if (total_elems > MAX_THRESH) { *lo = base_ptr; *hi = lo + (total_elems - 1); *left_ptr; *right_ptr; stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */ stack_node *top = stack + 1; while (STACK_NOT_EMPTY) { { *pivot = &pivot_buffer; { /* Select median value from among LO, MID, and HI. Rearrange LO and HI so the three values are sorted. This lowers the probability of picking a pathological pivot value and skips a comparison for both the LEFT_PTR and RIGHT_PTR. */ *mid = lo + ((hi - lo) >> 1); if ((*cmp) (*mid, *lo) < 0) SWAP (mid, lo); if ((*cmp) (*hi, *mid) < 0) { SWAP (mid, hi); if ((*cmp) (*mid, *lo) < 0) SWAP (mid, lo); } *pivot = *mid; pivot = &pivot_buffer; } left_ptr = lo + 1; right_ptr = hi - 1; /* Here's the famous ``collapse the walls'' section of quicksort. Gotta like those tight inner loops! They are the main reason that this algorithm runs much faster than others. */ do { while ((*cmp) (*left_ptr, *pivot) < 0) left_ptr += 1; while ((*cmp) (*pivot, *right_ptr) < 0) right_ptr -= 1; if (left_ptr < right_ptr) { SWAP (left_ptr, right_ptr); left_ptr += 1; right_ptr -= 1; } else if (left_ptr == right_ptr) { left_ptr += 1; right_ptr -= 1; break; } } while (left_ptr <= right_ptr); } /* Set up pointers for next iteration. First determine whether left and right partitions are below the threshold size. If so, ignore one or both. Otherwise, push the larger partition's bounds on the stack and continue sorting the smaller one. */ if ((right_ptr - lo) <= max_thresh) { if ((hi - left_ptr) <= max_thresh) /* Ignore both small partitions. */ POP (lo, hi); else /* Ignore small left partition. */ lo = left_ptr; } else if ((hi - left_ptr) <= max_thresh) /* Ignore small right partition. */ hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left partition indices. */ { PUSH (lo, right_ptr); lo = left_ptr; } else /* Push larger right partition indices. */ { PUSH (left_ptr, hi); hi = right_ptr; } } } /* Once the BASE_PTR array is partially sorted by quicksort the rest is completely sorted using insertion sort, since this is efficient for partitions below MAX_THRESH size. BASE_PTR points to the beginning of the array to sort, and END_PTR points at the very last element in the array (*not* one beyond it!). */ { *end_ptr = base_ptr + 1 * (total_elems - 1); *run_ptr; *tmp_ptr = base_ptr; *thresh = end_ptr *trav; for (trav = run_ptr + 1; --trav >= run_ptr;) { c = *trav; *hi, *lo; for (hi = lo = trav; (lo -= 1) >= tmp_ptr; hi = lo) *hi = *lo; *hi = c; } } } } return 1; } ptr + 1; (tmp_ptr = run_ptr += 1) <= end_ptr; ) { while ((*cmp) (*run_ptr, *(tmp_ptr -= 1)) < 0) ; if ((tmp_ptr += 1) != run_ptr) { *trav; forlibg++/g++-include/Map.hP 644 473 0 4566 4677677736 10201 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Map_h #pragma once #define _Map_h 1 #include #include ".defs.h" class Map { protected: int count; def; public: Map( dflt); int length(); // current number of items int empty(); virtual int contains( key); // is key mapped? virtual void clear(); // delete all items virtual & operator [] ( key) = 0; // access contents by key virtual void del( key) = 0; // delete entry virtual Pix first() = 0; // Pix of first item or 0 virtual void next(Pix& i) = 0; // advance to next or 0 virtual & key(Pix i) = 0; // access key at i virtual & contents(Pix i) = 0; // access contents at i virtual int owns(Pix i); // is i a valid Pix ? virtual Pix seek( key); // Pix of key & dflt(); // access default val void error(const char* msg); virtual int OK() = 0; // rep invariant }; inline int Map::length() { return count; } inline int Map::empty() { return count == 0; } inline & Map::dflt() { return def; } inline Map::Map( dflt) :def(dflt) { count = 0; } #endif // is i a valid Pix ? virtual Pix seek( key); // Pix of key & dflt(); /libg++/g++-include/OSLBag.ccP 644 473 0 6736 4677677736 10672 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".OSLBag.h" Pix OSLBag::seek( item, Pix i = 0) { if (i == 0) i = p.first(); else next(i); for (; i != 0; p.next(i)) { int cmp = CMP(item, p(i)); if (cmp == 0) return i; else if (cmp < 0) return 0; } return 0; } int OSLBag::nof( item) { int n = 0; for (Pix i = p.first(); i != 0; p.next(i)) { int cmp = CMP(item, p(i)); if (cmp == 0) ++n; else if (cmp < 0) break; } return n; } Pix OSLBag::add( item) { Pix i = p.first(); if (i == 0) { ++count; return p.prepend(item); } int cmp = CMP(item, p(i)); if (cmp <= 0) { ++count; return p.prepend(item); } else { Pix trail = i; p.next(i); for (;;) { if (i == 0) { ++count; return p.append(item); } cmp = CMP(item, p(i)); if (cmp <= 0) { ++count; return p.ins_after(trail, item); } else { trail = i; p.next(i); } } } } void OSLBag::del( item) { Pix i = p.first(); if (i == 0) return; int cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { --count; p.del_front(); } else { Pix trail = i; p.next(i); while (i != 0) { cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { --count; p.del_after(trail); return; } else { trail = i; p.next(i); } } } } void OSLBag::remove( item) { Pix i = p.first(); if (i == 0) return; int cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { do { --count; p.del_front(); i = p.first(); } while (i != 0 && EQ(item, p(i))); } else { Pix trail = i; p.next(i); while (i != 0) { cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { do { --count; p.del_after(trail); i = trail; next(i); } while (i != 0 && EQ(item, p(i))); return; } else { trail = i; p.next(i); } } } } int OSLBag::OK() { int v = p.OK(); v &= count == p.length(); Pix trail = p.first(); if (trail == 0) v &= count == 0; else { Pix i = trail; next(i); while (i != 0) { v &= CMP(p(trail), p(i)) <= 0; trail = i; next(i); } } if (!v) error("invariant failure"); return v; } il; next(i); } wlibg++/g++-include/OSLBag.hP 644 473 0 4065 4677677736 10525 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _OSLBag_h #pragma once #define _OSLBag_h 1 #include ".Bag.h" #include ".SLList.h" class OSLBag : public Bag { protected: SLList p; public: OSLBag(); OSLBag(const OSLBag&); Pix add( item); void del( item); void remove(item); int contains( item); int nof( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item, Pix from = 0); int OK(); }; inline OSLBag::OSLBag() : p() { count = 0; } inline OSLBag::OSLBag(const OSLBag& s) : p(s.p) { count = s.count; } inline Pix OSLBag::first() { return p.first(); } inline void OSLBag::next(Pix & idx) { p.next(idx); } inline & OSLBag::operator ()(Pix idx) { return p(idx); } inline void OSLBag::clear() { count = 0; p.clear(); } inline int OSLBag::owns (Pix idx) { return p.owns(idx); } inline int OSLBag::contains( item) { return seek(item) != 0; } #endif OSLBag::OSLBag() : p() { count = 0; } inline OSLBag::OSLBag(const OSLBag& s) : p(s.p) { count = s.count; } inline Pix OSLBag::first() { return p.first(); } inline void OSLBag::next(Pix & idx) { p.next(idx); } inline & OSLBag::operator ()(Pix idx) { return p(idx); } inline void OSLBag::clear() { count = 0; p.clear(); } inline int OSLBag::owns (Pix idx) { return p.owns(idx); } inline int OSLBag::contailibg++/g++-include/OSLSet.ccP 644 473 0 12740 4677677736 10744 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".OSLSet.h" Pix OSLSet::seek( item) { for (Pix i = p.first(); i != 0; p.next(i)) { int cmp = CMP(item, p(i)); if (cmp == 0) return i; else if (cmp < 0) return 0; } return 0; } Pix OSLSet::add( item) { Pix i = p.first(); if (i == 0) { ++count; return p.prepend(item); } int cmp = CMP(item, p(i)); if (cmp == 0) return i; else if (cmp < 0) { ++count; return p.prepend(item); } else { Pix trail = i; p.next(i); for (;;) { if (i == 0) { ++count; return p.append(item); } cmp = CMP(item, p(i)); if (cmp == 0) return i; else if (cmp < 0) { ++count; return p.ins_after(trail, item); } else { trail = i; p.next(i); } } } } void OSLSet::del( item) { Pix i = p.first(); if (i == 0) return; int cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { --count; p.del_front(); } else { Pix trail = i; p.next(i); while (i != 0) { cmp = CMP(item, p(i)); if (cmp < 0) return; else if (cmp == 0) { --count; p.del_after(trail); return; } else { trail = i; p.next(i); } } } } int OSLSet::operator <= (OSLSet& b) { if (count > b.count) return 0; Pix i = first(); Pix j = b.first(); for (;;) { if (i == 0) return 1; else if (j == 0) return 0; int cmp = CMP(p(i), b.p(j)); if (cmp == 0) { next(i); b.next(j); } else if (cmp < 0) return 0; else b.next(j); } } int OSLSet::operator == (OSLSet& b) { if (count != b.count) return 0; if (count == 0) return 1; Pix i = p.first(); Pix j = b.p.first(); while (i != 0) { if (!EQ(p(i),b.p(j))) return 0; next(i); b.next(j); } return 1; } void OSLSet::operator |= (OSLSet& b) { if (&b == this || b.count == 0) return; else { Pix j = b.p.first(); Pix i = p.first(); Pix trail = 0; for (;;) { if (j == 0) return; else if (i == 0) { for (; j != 0; b.next(j)) { ++count; p.append(b.p(j)); } return; } int cmp = CMP(p(i), b.p(j)); if (cmp <= 0) { if (cmp == 0) b.next(j); trail = i; next(i); } else { ++count; if (trail == 0) trail = p.prepend(b.p(j)); else trail = p.ins_after(trail, b.p(j)); b.next(j); } } } } void OSLSet::operator -= (OSLSet& b) { if (&b == this) clear(); else if (count != 0 && b.count != 0) { Pix i = p.first(); Pix j = b.p.first(); Pix trail = 0; for (;;) { if (j == 0 || i == 0) return; int cmp = CMP(p(i), b.p(j)); if (cmp == 0) { --count; b.next(j); if (trail == 0) { p.del_front(); i = p.first(); } else { next(i); p.del_after(trail); } } else if (cmp < 0) { trail = i; next(i); } else b.next(j); } } } void OSLSet::operator &= (OSLSet& b) { if (b.count == 0) clear(); else if (&b != this && count != 0) { Pix i = p.first(); Pix j = b.p.first(); Pix trail = 0; for (;;) { if (i == 0) return; else if (j == 0) { if (trail == 0) { p.clear(); count = 0; } else { while (i != 0) { --count; next(i); p.del_after(trail); } } return; } int cmp = CMP(p(i), b.p(j)); if (cmp == 0) { trail = i; next(i); b.next(j); } else if (cmp < 0) { --count; if (trail == 0) { p.del_front(); i = p.first(); } else { next(i); p.del_after(trail); } } else b.next(j); } } } int OSLSet::OK() { int v = p.OK(); v &= count == p.length(); Pix trail = p.first(); if (trail == 0) v &= count == 0; else { Pix i = trail; next(i); while (i != 0) { v &= CMP(p(trail), p(i)) < 0; trail = i; next(i); } } if (!v) error("invariant failure"); return v; } .del_front(); i = p.filibg++/g++-include/OSLSet.hP 644 473 0 4475 4677677736 10574 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _OSLSet_h #pragma once #define _OSLSet_h 1 #include ".Set.h" #include ".SLList.h" class OSLSet : public Set { protected: SLList p; public: OSLSet(); OSLSet(const OSLSet&); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item); void operator |= (OSLSet& b); void operator -= (OSLSet& b); void operator &= (OSLSet& b); int operator == (OSLSet& b); int operator != (OSLSet& b); int operator <= (OSLSet& b); int OK(); }; inline OSLSet::OSLSet() : p() { count = 0; } inline OSLSet::OSLSet(const OSLSet& s) : p(s.p) { count = s.count; } inline Pix OSLSet::first() { return p.first(); } inline void OSLSet::next(Pix & idx) { p.next(idx); } inline & OSLSet::operator ()(Pix idx) { return p(idx); } inline void OSLSet::clear() { count = 0; p.clear(); } inline int OSLSet::contains ( item) { return seek(item) != 0; } inline int OSLSet::owns (Pix idx) { return p.owns(idx); } inline int OSLSet::operator != (OSLSet& b) { return !(*this == b); } #endif >OSLSet& s) : p(s.p) { count = s.count; } inline Pix OSLSet::first() { return p.first(); } inline void OSLSet::next(Pix & idx) { p.next(idx); } inline & OSLSet::operator ()(Pilibg++/g++-include/OXPBag.ccP 644 473 0 11226 4677677737 10712 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".OXPBag.h" Pix OXPBag::seek( item, Pix i = 0) { if (i == 0) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { while (mid > p.low() && EQ(item, p[mid - 1])) --mid; return p.index_to_Pix(mid); } else if (cmp < 0) h = mid - 1; else l = mid + 1; } return 0; } int cmp = CMP(item, p(i)); if (cmp == 0) { next(i); return (EQ(item, p(i)))? i : 0; } else if (cmp < 0) { int ind = p.Pix_to_index(i); int l = ind; int h = p.high(); while (l <= h) { int mid = (l + h) / 2; cmp = CMP(item, p[mid]); if (cmp == 0) { while (mid > ind && EQ(item, p[mid - 1])) --mid; return p.index_to_Pix(mid); } else if (cmp < 0) h = mid - 1; else l = mid + 1; } return 0; } else return 0; } int OXPBag::nof( item) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { l = h = mid; while (l > p.low() && EQ(item, p[l - 1])) --l; while (h < p.high() && EQ(item, p[h + 1])) ++h; return h - l + 1; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } return 0; } Pix OXPBag::add( item) { if (count == 0) { ++count; return p.index_to_Pix(p.add_high(item)); } int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { l = mid; break; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } // add on whichever side is shortest ++count; if (l == p.fence()) return p.index_to_Pix(p.add_high(item)); else if (l == p.low()) return p.index_to_Pix(p.add_low(item)); else { if (p.high() - l < l - p.low()) { h = p.add_high(p.high_element()); for (int i = h - 1; i > l; --i) p[i] = p[i-1]; } else { --l; h = p.add_low(p.low_element()); for (int i = h + 1; i < l; ++i) p[i] = p[i+1]; } p[l] = item; return p.index_to_Pix(l); } } void OXPBag::del( item) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { --count; if (p.high() - mid < mid - p.low()) { for (int i = mid; i < p.high(); ++i) p[i] = p[i+1]; p.del_high(); } else { for (int i = mid; i > p.low(); --i) p[i] = p[i-1]; p.del_low(); } return; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } } void OXPBag::remove( item) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { l = h = mid; while (l > p.low() && EQ(item, p[l - 1])) --l; while (h < p.high() && EQ(item, p[h + 1])) ++h; int n = h - l + 1; count -= n; if (p.high() - h < l - p.low()) { h = p.high() - n; for (int i = l; i <= h; ++i) p[i] = p[i+n]; while (n-- > 0) p.del_high(); } else { l = p.low() + n; for (int i = h; i >= l; --i) p[i] = p[i-n]; while (n-- > 0) p.del_low(); } return; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } } int OXPBag::OK() { int v = p.OK(); v &= count == p.length(); for (int i = p.low(); i < p.high(); ++i) v &= CMP(p[i], p[i+1]) <= 0; if (!v) error("invariant failure"); return v; } = l; i <= h; ++i) p[i] = p[i+n]; while (n-- > 0) p.del_high(); } else { l = p.low() + n; for (int i = h; i >= l; --i) p[i] = p[i-n]; while (n-- > 0) p.del_low(); } return; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } } int OXPBag::OK() { int v = p.OK(); v &libg++/g++-include/OXPBag.hP 644 473 0 2352 4677677737 10534 #ifndef _OXPBag_h #pragma once #define _OXPBag_h 1 #include ".Bag.h" #include ".XPlex.h" class OXPBag : public Bag { protected: XPlex p; public: OXPBag(int chunksize = DEFAULT_INITIAL_CAPACITY); OXPBag(const OXPBag&); Pix add( item); void del( item); void remove(item); int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item, Pix from = 0); int OK(); }; inline OXPBag::OXPBag(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) { count = 0; } inline OXPBag::OXPBag(const OXPBag& s) : p(s.p) { count = s.count; } inline Pix OXPBag::first() { return p.first(); } inline void OXPBag::next(Pix & idx) { p.next(idx); } inline & OXPBag::operator ()(Pix idx) { return p(idx); } inline void OXPBag::clear() { count = 0; p.clear(); } inline int OXPBag::owns (Pix idx) { return p.owns(idx); } inline int OXPBag::contains( item) { return seek(item) != 0; } #endif CITY) : p(chunksize) { count = 0; } inline OXPBag::OXPBag(const OXPBag& s) : p(s.p) { count = s.count; } inline Pix OXPBag::first() { return p.first(); } inline void OXPBag::next(Pix & idx) { p.next(idx); } inline & OXPBag::operator ()(Pix libg++/g++-include/OXPSet.ccP 644 473 0 13051 4677677737 10752 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".OXPSet.h" Pix OXPSet::seek( item) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) return p.index_to_Pix(mid); else if (cmp < 0) h = mid - 1; else l = mid + 1; } return 0; } Pix OXPSet::add( item) { if (count == 0) { ++count; return p.index_to_Pix(p.add_high(item)); } int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) return p.index_to_Pix(mid); else if (cmp < 0) h = mid - 1; else l = mid + 1; } // add on whichever side is shortest ++count; if (l == p.fence()) return p.index_to_Pix(p.add_high(item)); else if (l == p.low()) return p.index_to_Pix(p.add_low(item)); else { if (p.fence() - l < l - p.low()) { h = p.add_high(p.high_element()); for (int i = h - 1; i > l; --i) p[i] = p[i-1]; } else { --l; h = p.add_low(p.low_element()); for (int i = h + 1; i < l; ++i) p[i] = p[i+1]; } p[l] = item; return p.index_to_Pix(l); } } void OXPSet::del( item) { int l = p.low(); int h = p.high(); while (l <= h) { int mid = (l + h) / 2; int cmp = CMP(item, p[mid]); if (cmp == 0) { --count; if (p.high() - mid < mid - p.low()) { for (int i = mid; i < p.high(); ++i) p[i] = p[i+1]; p.del_high(); } else { for (int i = mid; i > p.low(); --i) p[i] = p[i-1]; p.del_low(); } return; } else if (cmp < 0) h = mid - 1; else l = mid + 1; } } int OXPSet::operator <= (OXPSet& b) { if (count > b.count) return 0; int i = p.low(); int j = b.p.low(); for (;;) { if (i >= p.fence()) return 1; else if (j >= b.p.fence()) return 0; int cmp = CMP(p[i], b.p[j]); if (cmp == 0) { ++i; ++j; } else if (cmp < 0) return 0; else ++j; } } int OXPSet::operator == (OXPSet& b) { int n = count; if (n != b.count) return 0; if (n == 0) return 1; int i = p.low(); int j = b.p.low(); while (n-- > 0) if (!EQ(p[i++], b.p[j++])) return 0; return 1; } void OXPSet::operator |= (OXPSet& b) { if (&b == this || b.count == 0) return; else if (b.count <= 2) // small b -- just add for (Pix i = b.first(); i; b.next(i)) add(b(i)); else { // strategy: merge into top of p, simultaneously killing old bottom int oldfence = p.fence(); int i = p.low(); int j = b.p.low(); for (;;) { if (i == oldfence) { while (j < b.p.fence()) p.add_high(b.p[j++]); break; } else if (j == b.p.fence()) { while (i++ < oldfence) { p.add_high(p.low_element()); p.del_low(); } break; } int cmp = CMP(p[i], b.p[j]); if (cmp <= 0) { ++i; if (cmp == 0) ++j; p.add_high(p.low_element()); p.del_low(); } else p.add_high(b.p[j++]); } count = p.length(); } } void OXPSet::operator -= (OXPSet& b) { if (&b == this) clear(); else if (count != 0 && b.count != 0) { int i = p.low(); int k = i; int j = b.p.low(); int oldfence = p.fence(); for (;;) { if (i >= oldfence) break; else if (j >= b.p.fence()) { if (k != i) while (i < oldfence) p[k++] = p[i++]; else k = oldfence; break; } int cmp = CMP(p[i], b.p[j]); if (cmp == 0) { ++i; ++j; } else if (cmp < 0) { if (k != i) p[k] = p[i]; ++i; ++k; } else j++; } while (k++ < oldfence) { --count; p.del_high(); } } } void OXPSet::operator &= (OXPSet& b) { if (b.count == 0) clear(); else if (&b != this && count != 0) { int i = p.low(); int k = i; int j = b.p.low(); int oldfence = p.fence(); for (;;) { if (i >= oldfence || j >= b.p.fence()) break; int cmp = CMP(p[i], b.p[j]); if (cmp == 0) { if (k != i) p[k] = p[i]; ++i; ++k; ++j; } else if (cmp < 0) ++i; else ++j; } while (k++ < oldfence) { --count; p.del_high(); } } } int OXPSet::OK() { int v = p.OK(); v &= count == p.length(); for (int i = p.low(); i < p.high(); ++i) v &= CMP(p[i], p[i+1]) < 0; if (!v) error("invariant failure"); return v; } nce || j >= b.p.fence()) break; int cmp = CMP(p[i], b.p[j]); if (cmp == 0) { if (k != i) p[k] = p[i]; ++i; ++k; ++j; } else if (cmp < 0) ++i; else ++j; } while (k++ < oldfence) { --count; p.del_high(); } } } int OXPSet::OK() { int v = p.OK(); v &= count == p.length(); for (int i = p.low(); i < p.high(); ++i) v &= CMP(p[i], p[i+1]) < 0; if (!v) elibg++/g++-include/OXPSet.hP 644 473 0 4634 4677677737 10603 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _OXPSet_h #pragma once #define _OXPSet_h 1 #include ".Set.h" #include ".XPlex.h" class OXPSet : public Set { protected: XPlex p; public: OXPSet(int chunksize = DEFAULT_INITIAL_CAPACITY); OXPSet(const OXPSet&); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item); void operator |= (OXPSet& b); void operator -= (OXPSet& b); void operator &= (OXPSet& b); int operator == (OXPSet& b); int operator != (OXPSet& b); int operator <= (OXPSet& b); int OK(); }; inline OXPSet::OXPSet(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) { count = 0; } inline OXPSet::OXPSet(const OXPSet& s) : p(s.p) { count = s.count; } inline Pix OXPSet::first() { return p.first(); } inline void OXPSet::next(Pix & idx) { p.next(idx); } inline & OXPSet::operator ()(Pix idx) { return p(idx); } inline void OXPSet::clear() { count = 0; p.clear(); } inline int OXPSet::contains ( item) { return seek(item) != 0; } inline int OXPSet::owns (Pix idx) { return p.owns(idx); } inline int OXPSet::operator != (OXPSet& b) { return !(*this == b); } #endif >OXPSet& s) : p(s.p) { count = s.count; } inline Pix OXPSet::first() { return p.first(); } inlibg++/g++-include/PHPQ.ccP 644 473 0 16447 4677677740 10406 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".PHPQ.h" // // This defines a Pairing Heap structure // // See ``The Pairing Heap: A New Form of Self-Adjusting Heap'' // Fredman, Segdewick et al, // Algorithmica (1986) 1:111-129 // // In particular, this implements the pairing heap using the circular // list. // // PHPQ::PHPQ(int sz = DEFAULT_INITIAL_CAPACITY) { storage = 0; root = 0; count = 0; size = 0; prealloc(sz); } PHPQ::PHPQ(PHPQ& a) { storage = 0; root = 0; count = 0; size = 0; prealloc(a.size); for (Pix i = a.first(); i != 0; a.next(i)) enq(a(i)); } void PHPQ::prealloc(int newsize) { ++newsize; // leave a spot for freelist if (size != 0) { int news = size; while (news <= newsize) news = (news * 3) / 2; newsize = news; } // see if indices are OK PHPQNode test; test.sibling = 0; test.sibling = ~test.sibling; if ((unsigned long)newsize > (unsigned long)(test.sibling)) error("storage size exceeds index range"); if (storage == 0) { storage = new PHPQNode[size = newsize]; for (int i = 0; i < size; ++i) { storage[i].sibling = i + 1; storage[i].valid = 0; } storage[size-1].sibling = 0; } else { PHPQNode* newstor = new PHPQNode[newsize]; for (int i = 1; i < size; ++i) newstor[i] = storage[i]; delete [size] storage; storage = newstor; for (i = size; i < newsize; ++i) { storage[i].sibling = i + 1; storage[i].valid = 0; } storage[newsize-1].sibling = 0; storage[0].sibling = size; size = newsize; } } void PHPQ::clear() { for (int i = 0; i < size; ++i) { storage[i].sibling = i + 1; storage[i].valid = 0; } storage[size-1].sibling = 0; root = 0; count = 0; } Pix PHPQ::enq( item) { ++count; if (storage[0].sibling == 0) prealloc(count); int cell = storage[0].sibling; storage[0].sibling = storage[cell].sibling; storage[cell].sibling = 0; storage[cell].children = 0; storage[cell].item = item; storage[cell].valid = 1; if (root == 0) { root = cell; return Pix(root); } else { int parent; int child; if (LE(storage[root].item, storage[cell].item)) { parent = root; child = cell; } else { parent = cell; child = root; } int popsKid = storage[parent].children; if (popsKid == 0) { storage[parent].children = child; storage[child].sibling = child; } else { int temp = storage[popsKid].sibling; storage[popsKid].sibling = child; storage[child].sibling = temp; storage[parent].children = child; } root = parent; return Pix(cell); } } // // Item removal is the most complicated routine. // // We remove the root (should there be one) and then select a new // root. The siblings of the root are in a circular list. We continue // to pair elements in this list until there is a single element. // This element will be the new root. void PHPQ::del_front() { int valid = 0; do { if (root == 0) return; if (valid = storage[root].valid) --count; storage[root].valid = 0; int child = storage[root].children; storage[root].sibling = storage[0].sibling; storage[0].sibling = root; if (child == 0) { root = 0; return; } else { while(storage[child].sibling != child) { // We have at least two kids, but we may only have // two kids. So, oneChild != child, but it is possible // that twoChild == child. int oneChild = storage[child].sibling; int twoChild = storage[oneChild].sibling; // Remove the two from the sibling list storage[child].sibling = storage[twoChild].sibling; storage[oneChild].sibling = 0; storage[twoChild].sibling = 0; int bestChild; int worstChild; if (LE(storage[oneChild].item, storage[twoChild].item)) { bestChild = oneChild; worstChild = twoChild; } else { bestChild = twoChild; worstChild = oneChild; } int popsKid = storage[bestChild].children; if (popsKid == 0) { storage[bestChild].children = worstChild; storage[worstChild].sibling = worstChild; } else { int temp = storage[popsKid].sibling; storage[popsKid].sibling = worstChild; storage[worstChild].sibling = temp; storage[bestChild].children = worstChild; } if (twoChild == child) { // We have reduced the two to one, so we'll be exiting. child = bestChild; storage[child].sibling = child; } else { // We've removed two siblings, now we need to insert // the better of the two storage[bestChild].sibling = storage[child].sibling; storage[child].sibling = bestChild; child = storage[bestChild].sibling; } } root = child; } } while ( !valid ); } void PHPQ::del(Pix p) { if (p == 0) error("null Pix"); int i = int(p); if (storage[i].valid) { if (i == root) del_front(); else { storage[i].valid = 0; --count; } } } Pix PHPQ::seek( key) { for (int i = 1; i < size; ++i) if (storage[i].valid && EQ(storage[i].item, key)) return Pix(i); return 0; } Pix PHPQ::first() { for (int i = 1; i < size; ++i) if (storage[i].valid) return Pix(i); return 0; } void PHPQ::next(Pix& p) { if (p == 0) return; for (int i = int(p)+1; i < size; ++i) if (storage[i].valid) { p = Pix(i); return; } p = 0; } int PHPQ::OK() { int v = storage != 0; int n = check_sibling_list(root, 0); v &= n == count; int ct = MAXLONG; n = 0; int f = storage[0].sibling; while (f != 0 && ct-- > 0) { f = storage[f].sibling; ++n; } v &= ct > 0; v &= n <= size - count; if (!v) error("invariant failure"); return v; } int PHPQ::check_sibling_list(int t, int cnt) { if (t != 0) { int s = t; long ct = MAXLONG; // Lots of chances to find self! do { if (storage[s].valid) cnt++; cnt += check_sibling_list(storage[s].children, cnt); s = storage[s].sibling; } while (ct-- > 0 && s != t && s != 0); if (ct <= 0) return -1; } return cnt; } f = storage[f].sibling; ++n; } v &= ct > 0; v &= n <= size - count; if (!v) error("invariant failure"); return v; } int PHPQ::check_sibling_list(int t, int cnt) { if (t != 0) { int s = tlibg++/g++-include/PHPQ.hP 644 473 0 4713 4677677740 10221 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef PHPQ_h #pragma once #define PHPQ_h 1 #include ".PQ.h" #ifndef PHPQIndex #define PHPQIndex unsigned short #endif struct PHPQNode { PHPQIndex sibling; PHPQIndex children; item; char valid; }; class PHPQ : public PQ { PHPQNode* storage; // table -- freelist in storage[0].sibling int root; int size; void prealloc(int); int check_sibling_list(int, int); public: PHPQ(int sz = DEFAULT_INITIAL_CAPACITY); PHPQ(PHPQ&); ~PHPQ(); Pix enq( item); deq(); & front(); void del_front(); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); void del(Pix i); Pix seek( item); int OK(); // rep invariant }; inline PHPQ::~PHPQ() { delete [size] storage; } inline PHPQ::deq() { if (count == 0) error("deq of empty PQ"); x = storage[root].item; del_front(); return x; } inline & PHPQ::front() { if (count == 0) error("front of empty PQ"); return storage[root].item; } inline int PHPQ::contains( item) { return seek(item) != 0; } inline & PHPQ::operator() (Pix p) { if (p == 0) error("null Pix"); return storage[int(p)].item; } #endif // rep invariant }; inline PHPQ::~PHPQ() { libg++/g++-include/PQ.ccP 644 473 0 2721 4677677740 10124 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".PQ.h" PQ::deq() { x = front(); del_front(); return x; } Pix PQ::seek( item) { for (Pix i = first(); i != 0 && !(EQ((*this)(i), item)); next(i)); return i; } int PQ::owns(Pix idx) { if (idx == 0) return 0; for (Pix i = first(); i; next(i)) if (i == idx) return 1; return 0; } void PQ::clear() { while (count != 0) del_front(); } int PQ::contains ( item) { return seek(item) != 0; } void PQ::error(const char* msg) { (*lib_error_handler)("PQ", msg); } PQ::deq() { x = front(); del_flibg++/g++-include/PQ.hP 644 473 0 4341 4677677740 7766 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _PQ_h #pragma once #define _PQ_h 1 #include #include ".defs.h" class PQ { protected: int count; public: int length(); // current number of items int empty(); virtual Pix enq( item) = 0; // add item; return Pix virtual deq(); // return & remove min virtual & front() = 0; // access min item virtual void del_front() = 0; // delete min item virtual int contains( item); // is item in PQ? virtual void clear(); // delete all items virtual Pix first() = 0; // Pix of first item or 0 virtual void next(Pix& i) = 0; // advance to next or 0 virtual & operator () (Pix i) = 0; // access item at i virtual void del(Pix i) = 0; // delete item at i virtual int owns(Pix i); // is i a valid Pix ? virtual Pix seek( item); // Pix of item void error(const char* msg); virtual int OK() = 0; // rep invariant }; inline int PQ::length() { return count; } inline int PQ::empty() { return count == 0; } #endif next or 0 virtual & operator () (Pix i) = 0; // access item at i virtual void del(Pix i) = 0; // delete item at i virtual int owns(Pix i); // is i a valid Pix ? virtual Pix seek( item); // Pix of item libg++/g++-include/Plex.ccP 644 473 0 10176 4677677740 10537 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".Plex.h" // IChunk support volatile void IChunk::error(const char* msg) const { (*lib_error_handler)("IChunk", msg); } volatile void IChunk::index_error() const { error("attempt to use invalid index"); } volatile void IChunk::empty_error() const { error("invalid use of empty chunk"); } volatile void IChunk::full_error() const { error("attempt to extend chunk beyond bounds"); } IChunk::IChunk(* d, int baseidx, int lowidx, int fenceidx, int topidx) { if (d == 0 || baseidx > lowidx || lowidx > fenceidx || fenceidx > topidx) error("inconsistent specification"); data = d; base = baseidx; low = lowidx; fence = fenceidx; top = topidx; nxt = prv = this; } void IChunk:: re_index(int lo) { int delta = lo - low; base += delta; low += delta; fence += delta; top += delta; } void IChunk::clear(int lo) { int s = top - base; low = base = fence = lo; top = base + s; } void IChunk::cleardown(int hi) { int s = top - base; low = top = fence = hi; base = top - s; } int IChunk:: OK() const { int v = data != 0; // have some data v &= base <= low; // ok, index-wise v &= low <= fence; v &= fence <= top; v &= nxt->prv == this; // and links are OK v &= prv->nxt == this; if (!v) error("invariant failure"); return(v); } // error handling volatile void Plex::error(const char* msg) const { (*lib_error_handler)("Plex", msg); } volatile void Plex::index_error() const { error("attempt to access invalid index"); } volatile void Plex::empty_error() const { error("attempted operation on empty plex"); } volatile void Plex::full_error() const { error("attempt to increase size of plex past limit"); } // generic plex ops void Plex::append (const Plex& a) { for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); } void Plex::prepend (const Plex& a) { for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); } void Plex::reverse() { tmp; int l = low(); int h = high(); while (l < h) { tmp = (*this)[l]; (*this)[l] = (*this)[h]; (*this)[h] = tmp; next(l); prev(h); } } void Plex::fill(const x) { for (int i = lo; i < fnc; ++i) (*this)[i] = x; } void Plex::fill(const x, int lo, int hi) { for (int i = lo; i <= hi; ++i) (*this)[i] = x; } void Plex::del_chunk(IChunk* x) { if (x != 0) { x->unlink(); int sz = x->size(); * data = (*)(x->invalidate()); delete [sz] data; delete x; } } void Plex::invalidate() { IChunk* t = hd; if (t != 0) { IChunk* tail = tl(); while (t != tail) { IChunk* nxt = t->next(); del_chunk(t); t = nxt; } del_chunk(t); hd = 0; } } int Plex::reset_low(int l) { int old = lo; int diff = l - lo; if (diff != 0) { lo += diff; fnc += diff; IChunk* t = hd; do { t->re_index(t->low_index() + diff); t = t->next(); } while (t != hd); } return old; } } } void Plex::invalidate() { IChunk* t = hd; if (t != 0) { IChunk* tail = tl(); while (t != tail) { IChunk* nxt = t->next(); del_chunk(t); t = nxt; } del_chunk(t); hd = 0; } } int Plex::reset_low(int l) { int old = lo; int diff = l - lo; if (diff != 0) { lo += diff; fnc += diff; IChunk* t = hlibg++/g++-include/Plex.hP 644 473 0 31623 4677677741 10402 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Plex_h #pragma once #define _Plex_h 1 #include #include #include ".defs.h" // Plexes are made out of IChunks #include class IChunk { //public: // kludge until C++ `protected' policies settled protected: * data; // data, from client int base; // lowest possible index int low; // lowest valid index int fence; // highest valid index + 1 int top; // highest possible index + 1 IChunk* nxt; // circular links IChunk* prv; public: // constructors IChunk(* d, // ptr to array of elements int base_idx, // initial indices int low_idx, int fence_idx, int top_idx); virtual ~IChunk(); // status reports int size() const; // number of slots virtual int empty() const ; virtual int full() const ; int can_grow_high () const ; // there is space to add data int can_grow_low () const; int base_index() const; // lowest possible index; int low_index() const; // lowest actual index; virtual int first_index() const; // lowest valid index or fence if none virtual int last_index() const; // highest valid index or low-1 if none int fence_index() const; // highest actual index + 1 int top_index() const; // highest possible index + 1 // indexing conversion int possible_index(int i) const; // i between base and top int actual_index(int i) const; // i between low and fence virtual int valid_index(int i) const; // i not deleted (mainly for mchunks) int possible_pointer(const * p) const; // same for ptr int actual_pointer(const * p) const; virtual int valid_pointer(const * p) const; * pointer_to(int i) const ; // pointer to data indexed by i // caution: i is not checked for validity int index_of(const * p) const; // index of data pointed to by p // caution: p is not checked for validity virtual int succ(int idx) const; // next valid index or fence if none virtual int pred(int idx) const; // previous index or low - 1 if none virtual * first_pointer() const; // pointer to first valid pos or 0 virtual * last_pointer() const; // pointer to first valid pos or 0 virtual * succ(* p) const; // next pointer or 0 virtual * pred(* p) const; // previous pointer or 0 // modification virtual * grow_high (); // return spot to add an element virtual * grow_low (); virtual void shrink_high (); // logically delete top index virtual void shrink_low (); virtual void clear(int lo); // reset to empty ch with base = lo virtual void cleardown(int hi); // reset to empty ch with top = hi void re_index(int lo); // re-index so lo is new low // chunk traversal IChunk* next() const; IChunk* prev() const; void link_to_prev(IChunk* prev); void link_to_next(IChunk* next); void unlink(); // state checks * invalidate(); // mark self as invalid; return data // for possible deletion virtual int OK() const; // representation invariant volatile void error(const char*) const; volatile void empty_error() const; volatile void full_error() const; volatile void index_error() const; }; // Plex is a partly `abstract' class: few of the virtuals // are implemented at the Plex level, only in the subclasses class Plex { protected: IChunk* hd; // a chunk holding the data int lo; // lowest index int fnc; // highest index + 1 int csize; // size of the chunk void invalidate(); // mark so OK() is false void del_chunk(IChunk*); // delete a chunk IChunk* tl() const; // last chunk; int one_chunk() const; // true if hd == tl() public: // constructors, etc. Plex(); // no-op virtual ~Plex(); // Access functions virtual & operator [] (int idx) = 0; // access by index; virtual & operator () (Pix p) = 0; // access by Pix; virtual & high_element () = 0; // access high element virtual & low_element () = 0; // access low element // read-only versions for const Plexes virtual const & operator [] (int idx) const = 0; // access by index; virtual const & operator () (Pix p) const = 0; // access by Pix; virtual const & high_element () const = 0; // access high element virtual const & low_element () const = 0; // access low element // Index functions virtual int valid (int idx) const = 0; // idx is an OK index virtual int low() const = 0; // lowest index or fence if none virtual int high() const = 0; // highest index or low-1 if none int ecnef() const; // low limit index (low-1) int fence() const; // high limit index (high+1) virtual void prev(int& idx) const= 0; // set idx to preceding index // caution: pred may be out of bounds virtual void next(int& idx) const = 0; // set to next index // caution: succ may be out of bounds virtual Pix first() const = 0; // Pix to low element or 0 virtual Pix last() const = 0; // Pix to high element or 0 virtual void prev(Pix& pix) const = 0; // preceding pix or 0 virtual void next(Pix& pix) const = 0; // next pix or 0 virtual int owns(Pix p) const = 0; // p is an OK Pix // index<->Pix virtual int Pix_to_index(Pix p) const = 0; // get index via Pix virtual Pix index_to_Pix(int idx) const = 0; // Pix via index // Growth virtual int add_high(const elem) =0;// add new element at high end // return new high virtual int add_low(const elem) = 0; // add new low element, // return new low // Shrinkage virtual int del_high() = 0; // remove the element at high end // return new high virtual int del_low() = 0; // delete low element, return new lo // caution: del_low/high // does not necessarily // immediately call ::~ // operations on multiple elements virtual void fill(const x); // set all elements = x virtual void fill(const x, int from, int to); // fill from to to virtual void clear() = 0; // reset to zero-sized Plex virtual int reset_low(int newlow); // change low index,return old virtual void reverse(); // reverse in-place virtual void append(const Plex& a); // concatenate a copy virtual void prepend(const Plex& a); // prepend a copy // status virtual int can_add_high() const = 0; virtual int can_add_low() const = 0; int length () const; // number of slots int empty () const; // is the plex empty? virtual int full() const = 0; // it it full? int chunk_size() const; // report chunk size; virtual int OK() const = 0; // representation invariant volatile void error(const char* msg) const; volatile void index_error() const; volatile void empty_error() const; volatile void full_error() const; }; // IChunk ops inline int IChunk:: size() const { return top - base; } inline int IChunk:: base_index() const { return base; } inline int IChunk:: low_index() const { return low; } inline int IChunk:: fence_index() const { return fence; } inline int IChunk:: top_index() const { return top; } inline * IChunk:: pointer_to(int i) const { return &(data[i-base]); } inline int IChunk:: index_of(const * p) const { return ((int)p - (int)data) / sizeof() + base; } inline int IChunk:: possible_index(int i) const { return i >= base && i < top; } inline int IChunk:: possible_pointer(const * p) const { return p >= data && p < &(data[top-base]); } inline int IChunk:: actual_index(int i) const { return i >= low && i < fence; } inline int IChunk:: actual_pointer(const * p) const { return p >= data && p < &(data[fence-base]); } inline int IChunk:: can_grow_high () const { return fence < top; } inline int IChunk:: can_grow_low () const { return base < low; } inline * IChunk:: invalidate() { * p = data; data = 0; return p; } inline IChunk:: ~IChunk() {} inline IChunk* IChunk::prev() const { return prv; } inline IChunk* IChunk::next() const { return nxt; } inline void IChunk::link_to_prev(IChunk* prev) { nxt = prev->nxt; prv = prev; nxt->prv = this; prv->nxt = this; } inline void IChunk::link_to_next(IChunk* next) { prv = next->prv; nxt = next; nxt->prv = this; prv->nxt = this; } inline void IChunk::unlink() { IChunk* n = nxt; IChunk* p = prv; n->prv = p; p->nxt = n; prv = nxt = this; } inline int IChunk:: empty() const { return low == fence; } inline int IChunk:: full() const { return top - base == fence - low; } inline int IChunk:: first_index() const { return (low == fence)? fence : low; } inline int IChunk:: last_index() const { return (low == fence)? low - 1 : fence - 1; } inline int IChunk:: succ(int i) const { return (i < low) ? low : i + 1; } inline int IChunk:: pred(int i) const { return (i > fence) ? (fence - 1) : i - 1; } inline int IChunk:: valid_index(int i) const { return i >= low && i < fence; } inline int IChunk:: valid_pointer(const * p) const { return p >= &(data[low - base]) && p < &(data[fence - base]); } inline * IChunk:: grow_high () { if (!can_grow_high()) full_error(); return &(data[fence++ - base]); } inline * IChunk:: grow_low () { if (!can_grow_low()) full_error(); return &(data[--low - base]); } inline void IChunk:: shrink_high () { if (empty()) empty_error(); --fence; } inline void IChunk:: shrink_low () { if (empty()) empty_error(); ++low; } inline * IChunk::first_pointer() const { return (low == fence)? 0 : &(data[low - base]); } inline * IChunk::last_pointer() const { return (low == fence)? 0 : &(data[fence - base - 1]); } inline * IChunk::succ(* p) const { return ((p+1) < &(data[low - base]) || (p+1) >= &(data[fence - base])) ? 0 : (p+1); } inline * IChunk::pred(* p) const { return ((p-1) < &(data[low - base]) || (p-1) >= &(data[fence - base])) ? 0 : (p-1); } // generic Plex operations inline Plex::Plex() {} inline int Plex::chunk_size() const { return csize; } inline int Plex::ecnef () const { return lo - 1; } inline Plex:: ~Plex() { invalidate(); } inline int Plex::fence () const { return fnc; } inline int Plex::length () const { return fnc - lo; } inline int Plex::empty () const { return fnc == lo; } inline IChunk* Plex::tl() const { return hd->prev(); } inline int Plex::one_chunk() const { return hd == hd->prev(); } #endif e Plex::Plex() {} inline int Plex::chunk_size() const { return csize; } inline int Plex::ecnlibg++/g++-include/bool.h 644 473 0 134 4677677741 10236 #ifndef _bool_h #pragma once #define _bool_h 1 enum bool { FALSE = 0, TRUE = 1 }; #endif int Plex::fence () const { return fnc; } inline int Plex::length () const { return fnc - lo; } inline int Plex::empty () const { return fnc == lo; } inline IChunk* Plex::tl() const { return hd->prev(); } inline int Plex::one_chunk() const { return hd == hd->prev(); } #endif e Plex::Plex() {} inline int Plex::chunk_size() const { return csize; } inline int Plex::ecnlibg++/g++-include/Queue.hP 644 473 0 3251 4677677741 10532 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Queue_h #pragma once #define _Queue_h #include #include ".defs.h" class Queue { public: Queue(); ~Queue(); virtual void enq( item) = 0; virtual deq() = 0; virtual & front() = 0; virtual void del_front() = 0; virtual void clear() = 0; virtual int empty() = 0; virtual int full() = 0; virtual int length() = 0; void error(const char*); virtual int OK() = 0; }; inline Queue::Queue() {} inline Queue::~Queue() {} // error handling inline void Queue::error(const char* msg) { (*lib_error_handler)("Queue", msg); } #endif deq() = 0; virtual & front() = 0; virtual void del_front() = 0; virtual void clear() = 0; virtual int empty() = 0; virtual int full() = 0; virtual int length() = 0; void error(const char*); virtual int OK() = 0; }; inline libg++/g++-include/RPlex.ccP 644 473 0 24242 4677677741 10661 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".RPlex.h" typedef IChunk* _IChunk_ptr; RPlex:: RPlex() { lo = fnc = 0; csize = DEFAULT_INITIAL_CAPACITY; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, lo+csize)); hd = ch; maxch = MIN_NCHUNKS; lch = maxch / 2; fch = lch + 1; base = ch->base_index() - lch * csize; chunks = new _IChunk_ptr[maxch]; chunks[lch] = ch; } RPlex:: RPlex(int chunksize) { if (chunksize == 0) error("invalid constructor specification"); lo = fnc = 0; if (chunksize > 0) { csize = chunksize; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, csize+lo)); hd = ch; } else { csize = -chunksize; * data = new [csize]; set_cache(new IChunk(data, chunksize+lo, lo, fnc, fnc)); hd = ch; } maxch = MIN_NCHUNKS; lch = maxch / 2; fch = lch + 1; base = ch->base_index() - lch * csize; chunks = new _IChunk_ptr[maxch]; chunks[lch] = ch; } RPlex:: RPlex(int l, int chunksize) { if (chunksize == 0) error("invalid constructor specification"); lo = fnc = l; if (chunksize > 0) { csize = chunksize; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, csize)); hd = ch; } else { csize = -chunksize; * data = new [csize]; set_cache(new IChunk(data, chunksize, lo, fnc, fnc)); hd = ch; } maxch = MIN_NCHUNKS; lch = maxch / 2; fch = lch + 1; base = ch->base_index() - lch * csize; chunks = new _IChunk_ptr[maxch]; chunks[lch] = ch; } void RPlex::make_initial_chunks(int up = 1) { int count = 0; int need = fnc - lo; hd = 0; if (up) { int l = lo; do { ++count; int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; IChunk* h = new IChunk(data, l, l, l+sz, l+csize); if (hd != 0) h->link_to_next(hd); else hd = h; l += sz; need -= sz; } while (need > 0); } else { int hi = fnc; do { ++count; int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; IChunk* h = new IChunk(data, hi-csize, hi-sz, hi, hi); if (hd != 0) h->link_to_next(hd); hd = h; hi -= sz; need -= sz; } while (need > 0); } set_cache((IChunk*)hd); maxch = MIN_NCHUNKS; if (maxch < count * 2) maxch = count * 2; chunks = new _IChunk_ptr[maxch]; lch = maxch / 3; fch = lch + count; base = ch->base_index() - csize * lch; int k = lch; do { chunks[k++] = ch; set_cache(ch->next()); } while (ch != hd); } RPlex:: RPlex(int l, int hi, const initval, int chunksize = 0) { lo = l; fnc = hi + 1; if (chunksize == 0) { csize = fnc - l; make_initial_chunks(1); } else if (chunksize < 0) { csize = -chunksize; make_initial_chunks(0); } else { csize = chunksize; make_initial_chunks(1); } fill(initval); } RPlex::RPlex(const RPlex& a) { lo = a.lo; fnc = a.fnc; csize = a.csize; make_initial_chunks(); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } void RPlex::operator= (const RPlex& a) { if (&a != this) { invalidate(); lo = a.lo; fnc = a.fnc; csize = a.csize; make_initial_chunks(); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } } void RPlex::cache(const * p) const { const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) index_error(); } set_cache(t); } int RPlex::owns(Pix p) const { const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) return 0; } set_cache(t); return 1; } * RPlex::dosucc(const * p) const { if (p == 0) return 0; const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) return 0; } int i = t->index_of(p) + 1; if (i >= fnc) return 0; if (i >= t->fence_index()) t = (t->next()); set_cache(t); return t->pointer_to(i); } * RPlex::dopred(const * p) const { if (p == 0) return 0; const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->prev()); if (t == old) return 0; } int i = t->index_of(p) - 1; if (i < lo) return 0; if (i < t->low_index()) t = (t->prev()); set_cache(t); return (t->pointer_to(i)); } int RPlex::add_high(const elem) { IChunk* t = tl(); if (!t->can_grow_high()) { if (t->IChunk::empty() && one_chunk()) { t->clear(fnc); base = t->base_index() - lch * csize; } else { * data = new [csize]; t = (new IChunk(data, fnc, fnc, fnc,fnc+csize)); t->link_to_prev(tl()); if (fch == maxch) { maxch *= 2; IChunk** newch = new _IChunk_ptr [maxch]; bcopy(chunks, newch, fch * sizeof(_IChunk_ptr)); delete chunks; chunks = newch; } chunks[fch++] = t; } } *((t->IChunk::grow_high())) = elem; set_cache(t); return fnc++; } int RPlex::del_high () { if (empty()) empty_error(); IChunk* t = tl(); if (t->IChunk::empty()) // kill straggler first { IChunk* pred = t->prev(); del_chunk(t); t = (pred); --fch; } t->IChunk::shrink_high(); if (t->IChunk::empty() && !one_chunk()) { IChunk* pred = t->prev(); del_chunk(t); t = (pred); --fch; } set_cache(t); return --fnc - 1; } int RPlex::add_low (const elem) { IChunk* t = hd; if (!t->can_grow_low()) { if (t->IChunk::empty() && one_chunk()) { t->cleardown(lo); base = t->base_index() - lch * csize; } else { * data = new [csize]; hd = new IChunk(data, lo-csize, lo, lo, lo); hd->link_to_next(t); t = ( hd); if (lch == 0) { lch = maxch; fch += maxch; maxch *= 2; IChunk** newch = new _IChunk_ptr [maxch]; bcopy(chunks, &(newch[lch]), lch * sizeof(_IChunk_ptr)); delete chunks; chunks = newch; base = t->base_index() - (lch - 1) * csize; } chunks[--lch] = t; } } *((t->IChunk::grow_low())) = elem; set_cache(t); return --lo; } int RPlex::del_low () { if (empty()) empty_error(); IChunk* t = hd; if (t->IChunk::empty()) { hd = t->next(); del_chunk(t); t = hd; ++lch; } t->IChunk::shrink_low(); if (t->IChunk::empty() && !one_chunk()) { hd = t->next(); del_chunk(t); t = hd; ++lch; } set_cache(t); return ++lo; } void RPlex::append(const RPlex& a) { for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); } void RPlex::prepend (const RPlex& a) { for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); } void RPlex::reverse() { tmp; int l = lo; int h = fnc - 1; IChunk* loch = hd; IChunk* hich = tl(); while (l < h) { * lptr = loch->pointer_to(l); * hptr = hich->pointer_to(h); tmp = *lptr; *lptr = *hptr; *hptr = tmp; if (++l >= loch->fence_index()) loch = loch->next(); if (--h < hich->low_index()) hich = hich->prev(); } } void RPlex::fill(const x) { for (int i = lo; i < fnc; ++i) (*this)[i] = x; } void RPlex::fill(const x, int lo, int hi) { for (int i = lo; i <= hi; ++i) (*this)[i] = x; } void RPlex::clear() { for (int i = lch + 1; i < fch; ++i) del_chunk(chunks[i]); fch = lch + 1; set_cache(chunks[lch]); ch->IChunk::clear(lo); fnc = lo; } int RPlex::reset_low(int l) { int old = lo; int diff = l - lo; if (diff != 0) { lo += diff; fnc += diff; IChunk* t = hd; do { t->re_index(t->low_index() + diff); t = t->next(); } while (t != hd); } base = hd->base_index() - lch * csize; return old; } int RPlex::OK () const { int v = hd != 0 && ch != 0; // at least one chunk v &= fnc == tl()->fence_index(); // last chunk fnc == plex fnc v &= lo == hd->IChunk::low_index(); // first lo == plex lo v &= base == hd->base_index() - lch * csize; // base is correct; v &= lch < fch; v &= fch <= maxch; // within allocation; // loop for others: int k = lch; // to cross-check nch int found_ch = 0; // to make sure ch is in list; const IChunk* t = (hd); for (;;) { v &= chunks[k++] == t; // each chunk is at proper index if (t == ch) ++found_ch; v &= t->IChunk::OK(); // each chunk is OK if (t == tl()) break; else // and has indices contiguous to succ { v &= t->top_index() == t->next()->base_index(); if (t != hd) // internal chunks full { v &= !t->empty(); v &= !t->can_grow_low(); v &= !t->can_grow_high(); } t = t->next(); } } v &= found_ch == 1; v &= fch == k; if (!v) error("invariant failure"); return v; } t->IChunk::OK(); // each chunk is OK if (t == tl()) break; else // and has indices contiguous to succ { v &= t->top_index() == t->next()->base_index(); if (t != hd) // internal chunks full { v &= !t->empty(); v &= !t->can_grow_low(); libg++/g++-include/RPlex.hP 644 473 0 14735 4677677741 10531 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RPlex_h #pragma once #define _RPlex_h 1 #include ".Plex.h" // minimum number of chunks to index #ifndef MIN_NCHUNKS #define MIN_NCHUNKS 16 #endif class RPlex: public Plex { int base; // base index of lowest chunk int lch; // index of lowest used chunk int fch; // 1 + index of highest used chunk int maxch; // max chunks in array IChunk** chunks; // array of chunks IChunk* ch; // cached chunk void make_initial_chunks(int up = 1); void cache(int idx) const; void cache(const * p) const; * dopred(const * p) const; * dosucc(const * p) const; void set_cache(const IChunk* t) const; // logically, // not physically const public: RPlex(); // set low = 0; // fence = 0; // csize = default RPlex(int ch_size); // low = 0; // fence = 0; // csize = ch_size RPlex(int lo, // low = lo; int ch_size); // fence=lo // csize = ch_size RPlex(int lo, // low = lo int hi, // fence = hi+1 const initval,// fill with initval, int ch_size = 0); // csize= ch_size // or fence-lo if 0 RPlex(const RPlex&); ~RPlex(); void operator= (const RPlex&); // virtuals & high_element (); & low_element (); const & high_element () const; const & low_element () const; Pix first() const; Pix last() const; void prev(Pix& ptr) const; void next(Pix& ptr) const; int owns(Pix p) const; & operator () (Pix p); const & operator () (Pix p) const; int low() const; int high() const; int valid(int idx) const; void prev(int& idx) const; void next(int& x) const; & operator [] (int index); const & operator [] (int index) const; int Pix_to_index(Pix p) const; Pix index_to_Pix(int idx) const; int can_add_high() const; int can_add_low() const; int full() const; int add_high(const elem); int del_high (); int add_low (const elem); int del_low (); void fill(const x); void fill(const x, int from, int to); void clear(); void reverse(); void append(const RPlex& a); void prepend(const RPlex& a); int reset_low(int newlow); int OK () const; }; inline void RPlex::prev(int& idx) const { --idx; } inline void RPlex::next(int& idx) const { ++idx; } inline int RPlex::full () const { return 0; } inline int RPlex::can_add_high() const { return 1; } inline int RPlex::can_add_low() const { return 1; } inline int RPlex::valid (int idx) const { return idx >= lo && idx < fnc; } inline int RPlex::low() const { return lo; } inline int RPlex::high() const { return fnc - 1; } inline void RPlex::set_cache(const IChunk* t) const { ((RPlex*)(this))->ch = t; } inline void RPlex::cache(int idx) const { if (idx < lo || idx >= fnc) index_error(); set_cache(chunks[(idx - base) / csize]); } inline & RPlex::low_element () { cache(lo); return *(ch->pointer_to(lo)); } inline & RPlex::high_element () { cache(fnc-1); return *(ch->pointer_to(fnc - 1)); } inline const & RPlex::low_element () const { cache(lo); return *((const *)(ch->pointer_to(lo))); } inline const & RPlex::high_element () const { cache(fnc-1); return *((const *)(ch->pointer_to(fnc - 1))); } inline int RPlex::Pix_to_index(Pix p) const { if (!ch->actual_pointer(p)) cache(p); return ch->index_of(p); } inline Pix RPlex::index_to_Pix(int idx) const { if (!ch->actual_index(idx)) cache(idx); return (Pix)(ch->pointer_to(idx)); } inline Pix RPlex::first() const { return Pix(hd->IChunk::first_pointer()); } inline Pix RPlex::last() const { return Pix(tl()->IChunk::last_pointer()); } inline void RPlex::prev(Pix& p) const { Pix q = Pix(ch->IChunk::pred((*)p)); p = (q == 0)? Pix(dopred((*)p)) : q; } inline void RPlex::next(Pix& p) const { Pix q = Pix(ch->IChunk::succ((*)p)); p = (q == 0)? Pix(dosucc((*)p)) : q; } inline & RPlex:: operator () (Pix p) { return *((*)p); } inline & RPlex:: operator [] (int idx) { cache(idx); return *(ch->pointer_to(idx)); } inline const & RPlex:: operator () (Pix p) const { return *((const *)p); } inline const & RPlex:: operator [] (int idx) const { cache(idx); return *((const *)(ch->pointer_to(idx))); } inline RPlex::~RPlex() { delete chunks; } #endif Pix(ch->IChunk::succ((*)p)); libg++/g++-include/SLBag.ccP 644 473 0 4204 4677677741 10533 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".SLBag.h" int SLBag::OK() { int v = p.OK(); v &= count == p.length(); if (!v) error("invariant failure"); return v; } Pix SLBag::seek( item, Pix i = 0) { if (i == 0) i = first(); else next(i); for (; i != 0 && (!(EQ(p(i), item))); p.next(i)); return i; } int SLBag::nof( item) { int n = 0; for (Pix p = first(); p; next(p)) if (EQ((*this)(p), item)) ++n; return n; } void SLBag::del( item) { Pix i = p.first(); if (i == 0) return; else if (EQ(p(i), item)) { --count; p.del_front(); } else { Pix trail = i; p.next(i); while (i != 0) { if (EQ(p(i), item)) { --count; p.del_after(trail); return; } trail = i; p.next(i); } } } void SLBag::remove( item) { Pix i = p.first(); while (i != 0 && EQ(p(i), item)) { --count; p.del_front(); i = p.first(); } if (i != 0) { Pix trail = i; p.next(i); while (i != 0) { if (EQ(p(i), item)) { --count; p.del_after(trail); i = trail; p.next(i); } else { trail = i; p.next(i); } } } } return; } trail = i; p.next(i); } } } void SLBag::remove( item) { Pix i = p.first(); while (i != 0 && EQ(p(i), item)) { --count; p.del_front(); i = p.first(); } if (i != 0) { Pix trail = i; p.next(i); while (i != 0) { if (EQ(p(i), item)) { --count; p.del_after(trailibg++/g++-include/SLBag.hP 644 473 0 4157 4677677742 10405 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SLBag_h #pragma once #define _SLBag_h 1 #include ".Bag.h" #include ".SLList.h" class SLBag : public Bag { protected: SLList p; public: SLBag(); SLBag(const SLBag&); Pix add( item); void del( item); void remove(item); int contains( item); int nof( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item, Pix from = 0); int OK(); }; inline SLBag::SLBag() : p() { count = 0; } inline SLBag::SLBag(const SLBag& s) : p(s.p) { count = s.count; } inline Pix SLBag::first() { return p.first(); } inline void SLBag::next(Pix & idx) { p.next(idx); } inline & SLBag::operator ()(Pix idx) { return p(idx); } inline void SLBag::clear() { count = 0; p.clear(); } inline int SLBag::owns (Pix idx) { return p.owns(idx); } inline Pix SLBag::add( item) { ++count; return p.append(item); } inline int SLBag::contains( item) { return seek(item) != 0; } #endif (const SLBag& s) : p(s.p) { count = s.count; } inline Pix SLBag::first() { return p.first(); } inline void SLBag::next(Pix & idx) { p.next(idx); } inline & SLBag::operator ()(Pix idx) { return p(idx); } inline void SLBag::clear() { count = 0; p.clear(); } inline int SLBag::owns (Pix idx) { return p.owns(idx); } inline Pix SLBag::add( item) { ++coulibg++/g++-include/SLList.ccP 644 473 0 11630 4677677742 10777 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include ".SLList.h" void SLList::error(const char* msg) { (*lib_error_handler)("SLList", msg); } SLList::SLList(SLList& a) { if (a.last == 0) last = 0; else { SLListNode* p = a.last->tl; SLListNode* h = new SLListNode(p->hd); last = h; for (;;) { if (p == a.last) { last->tl = h; return; } p = p->tl; SLListNode* n = new SLListNode(p->hd); last->tl = n; last = n; } } } SLList& SLList::operator = (SLList& a) { if (last != a.last) { clear(); if (a.last != 0) { SLListNode* p = a.last->tl; SLListNode* h = new SLListNode(p->hd); last = h; for (;;) { if (p == a.last) { last->tl = h; break; } p = p->tl; SLListNode* n = new SLListNode(p->hd); last->tl = n; last = n; } } } return *this; } void SLList::clear() { if (last == 0) return; SLListNode* p = last->tl; last->tl = 0; last = 0; while (p != 0) { SLListNode* nxt = p->tl; delete(p); p = nxt; } } Pix SLList::prepend( item) { SLListNode* t = new SLListNode(item); if (last == 0) t->tl = last = t; else { t->tl = last->tl; last->tl = t; } return Pix(t); } Pix SLList::prepend(SLListNode* t) { if (t == 0) return 0; if (last == 0) t->tl = last = t; else { t->tl = last->tl; last->tl = t; } return Pix(t); } Pix SLList::append( item) { SLListNode* t = new SLListNode(item); if (last == 0) t->tl = last = t; else { t->tl = last->tl; last->tl = t; last = t; } return Pix(t); } Pix SLList::append(SLListNode* t) { if (t == 0) return 0; if (last == 0) t->tl = last = t; else { t->tl = last->tl; last->tl = t; last = t; } return Pix(t); } void SLList::join(SLList& b) { SLListNode* t = b.last; b.last = 0; if (last == 0) last = t; else if (t != 0) { SLListNode* f = last->tl; last->tl = t->tl; t->tl = f; last = t; } } Pix SLList::ins_after(Pix p, item) { SLListNode* u = (SLListNode*)p; SLListNode* t = new SLListNode(item); if (last == 0) t->tl = last = t; else if (u == 0) // ins_after 0 means prepend { t->tl = last->tl; last->tl = t; } else { t->tl = u->tl; u->tl = t; if (u == last) last = t; } return Pix(t); } void SLList::del_after(Pix p) { SLListNode* u = (SLListNode*)p; if (last == 0 || u == last) error("cannot del_after last"); if (u == 0) u = last; // del_after 0 means delete first SLListNode* t = u->tl; if (u == t) last = 0; else { u->tl = t->tl; if (last == t) last = u; } delete t; } int SLList::owns(Pix p) { SLListNode* t = last; if (t != 0 && p != 0) { do { if (Pix(t) == p) return 1; t = t->tl; } while (t != last); } return 0; } SLList::remove_front() { if (last == 0) error("remove_front of empty list"); SLListNode* t = last->tl; res = t->hd; if (t == last) last = 0; else last->tl = t->tl; delete t; return res; } int SLList::remove_front(& x) { if (last == 0) return 0; else { SLListNode* t = last->tl; x = t->hd; if (t == last) last = 0; else last->tl = t->tl; delete t; return 1; } } void SLList::del_front() { if (last == 0) error("del_front of empty list"); SLListNode* t = last->tl; if (t == last) last = 0; else last->tl = t->tl; delete t; } int SLList::OK() { int v = 1; if (last != 0) { SLListNode* t = last; long count = MAXLONG; // Lots of chances to find last! do { count--; t = t->tl; } while (count > 0 && t != last); v &= count > 0; } if (!v) error("invariant failure"); return v; } eturn 1; } } void SLList::del_front() { if (last == 0) error("del_front of empty list"); Slibg++/g++-include/SLList.hP 644 473 0 6575 4677677742 10635 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SLList_h #pragma once #define _SLList_h 1 #include #include ".defs.h" #ifndef _SLListNode_h #define _SLListNode_h 1 struct SLListNode { SLListNode* tl; hd; SLListNode(); SLListNode( h, SLListNode* t = 0); ~SLListNode(); }; inline SLListNode::SLListNode() {} inline SLListNode::SLListNode( h, SLListNode* t = 0) { hd = h; tl = t; } inline SLListNode::~SLListNode() {} typedef SLListNode* SLListNodePtr; #endif class SLList { protected: SLListNode* last; public: SLList(); SLList(SLList& a); ~SLList(); SLList& operator = (SLList& a); int empty(); int length(); void clear(); Pix prepend( item); Pix append( item); void join(SLList&); Pix prepend(SLListNode*); Pix append(SLListNode*); & operator () (Pix p); Pix first(); void next(Pix& p); int owns(Pix p); Pix ins_after(Pix p, item); void del_after(Pix p); & front(); & rear(); remove_front(); int remove_front(& x); void del_front(); void error(const char* msg); int OK(); }; inline SLList::~SLList() { clear(); } inline SLList::SLList() { last = 0; } inline int SLList::empty() { return last == 0; } inline int SLList::length() { int l = 0; SLListNode* t = last; if (t != 0) do { ++l; t = t->tl; } while (t != last); return l; } inline Pix SLList::first() { return (last == 0)? 0 : Pix(last->tl); } inline void SLList::next(Pix& p) { p = (p == 0 || p == last)? 0 : Pix(((SLListNode*)(p))->tl); } inline & SLList::operator () (Pix p) { if (p == 0) error("null Pix"); return ((SLListNode*)(p))->hd; } inline & SLList::front() { if (last == 0) error("front: empty list"); return last->tl->hd; } inline & SLList::rear() { if (last == 0) error("rear: empty list"); return last->hd; } #endif } inline Pix SLList::first() { return (last == 0)? 0 : Pix(last->tl); } inline void SLList::next(Pix& p) { p = (p == 0 libg++/g++-include/SLQueue.hP 644 473 0 4272 4677677742 10776 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SLQueue_h #pragma once #define _SLQueue_h #include ".SLList.h" #include ".Queue.h" class SLQueue : public Queue { SLList p; public: SLQueue(); SLQueue(const SLQueue& q); ~SLQueue(); void operator = (const SLQueue&); void enq( item); deq(); & front(); void del_front(); void clear(); int empty(); int full(); int length(); int OK(); }; inline SLQueue::SLQueue() :p() {} inline SLQueue::SLQueue(const SLQueue& q) : p(q.p) {} inline SLQueue::~SLQueue() {} inline void SLQueue::enq(item) { p.append(item); } inline SLQueue::deq() { return p.remove_front(); } inline & SLQueue::front() { return p.front(); } inline void SLQueue::del_front() { p.del_front(); } inline void SLQueue::operator =(const SLQueue& s) { p = s.p; } inline int SLQueue::empty() { return p.empty(); } inline int SLQueue::full() { return 0; } inline int SLQueue::length() { return p.length(); } inline int SLQueue::OK() { return p.OK(); } inline void SLQueue::clear() { p.clear(); } #endif SLQueue::deq() { return p.remove_front(); } inline & SLQueue::front() { return p.front(); } inline void SLQueue::del_front() { p.del_front(); } inline void SLQueue::operator =(const SLQueue& s) { p = s.p; } inline int SLQueue::empty() { return p.empty(); } inline int SLQueue::fulllibg++/g++-include/SLSet.ccP 644 473 0 3240 4677677742 10575 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".SLSet.h" int SLSet::OK() { int v = p.OK(); v &= count == p.length(); if (!v) error("invariant failure"); return v; } Pix SLSet::seek( item) { for (Pix i = p.first(); i != 0 && !EQ(p(i),item); p.next(i)); return i; } Pix SLSet::add( item) { Pix i = seek(item); if (i == 0) { ++count; i = p.append(item); } return i; } void SLSet::del( item) { Pix i = p.first(); if (i == 0) return; else if (EQ(p(i), item)) { --count; p.del_front(); } else { Pix trail = i; p.next(i); while (i != 0) { if (EQ(p(i), item)) { --count; p.del_after(trail); return; } trail = i; p.next(i); } } } rn i; } Pix SLSet::add( item) { Pix i = seek(item); if (i == 0) { ++count; i = p.append(item); } return i; } void SLSet::del( item) { Pix i = p.first(); if (i == 0) return; else if (EQ(p(i), item)) { --count; p.del_front(); } else { Pix trail = i; p.next(i); while (i != 0) libg++/g++-include/SLSet.hP 644 473 0 3724 4677677742 10446 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SLSet_h #pragma once #define _SLSet_h 1 #include ".Set.h" #include ".SLList.h" class SLSet : public Set { protected: SLList p; public: SLSet(); SLSet(const SLSet&); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item); int OK(); }; inline SLSet::SLSet() : p() { count = 0; } inline SLSet::SLSet(const SLSet& s) : p(s.p) { count = s.count; } inline Pix SLSet::first() { return p.first(); } inline void SLSet::next(Pix & idx) { p.next(idx); } inline & SLSet::operator ()(Pix idx) { return p(idx); } inline void SLSet::clear() { count = 0; p.clear(); } inline int SLSet::contains ( item) { return seek(item) != 0; } inline int SLSet::owns (Pix idx) { return p.owns(idx); } #endif inline SLSet::SLSet() : p() { count = libg++/g++-include/SLStack.hP 644 473 0 4302 4677677743 10752 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SLStack_h #pragma once #define _SLStack_h 1 #include ".SLList.h" #include ".Stack.h" class SLStack : public Stack { SLList p; public: SLStack(); SLStack(const SLStack& s); ~SLStack(); void operator = (const SLStack&); void push( item); pop(); & top(); void del_top(); int empty(); int full(); int length(); void clear(); int OK(); }; inline SLStack::SLStack() :p() {} inline SLStack::SLStack(const SLStack& a) : p(a.p) {} inline SLStack::~SLStack() {} inline void SLStack::push(item) { p.prepend(item); } inline SLStack::pop() { return p.remove_front(); } inline & SLStack::top() { return p.front(); } inline void SLStack::del_top() { p.del_front(); } inline void SLStack::operator =(const SLStack& s) { p = s.p; } inline int SLStack::empty() { return p.empty(); } inline int SLStack::full() { return 0; } inline int SLStack::length() { return p.length(); } inline int SLStack::OK() { return p.OK(); } inline void SLStack::clear() { p.clear(); } #endif SLStack::pop() { return p.remove_front(); } inline & SLStack::top() { return p.front(); } inline void SLStack::del_top() { p.del_front(); } inline void SLStack::operator =(const SLStack& s) { p = s.p; } inline int SLStack::empty() { return p.empty(); } inline int SLStack::libg++/g++-include/Set.ccP 644 473 0 4652 4677677743 10347 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".Set.h" Pix Set::seek( item) { for (Pix i = first(); i != 0 && !(EQ((*this)(i), item)); next(i)); return i; } int Set::owns(Pix idx) { if (idx == 0) return 0; for (Pix i = first(); i; next(i)) if (i == idx) return 1; return 0; } void Set::clear() { Pix i = first(); while (i != 0) { del((*this)(i)); i = first(); } } int Set::contains ( item) { return seek(item) != 0; } int Set::operator <= (Set& b) { if (count > b.count) return 0; if (count == 0) return 1; for (Pix i = first(); i; next(i)) if (b.seek((*this)(i)) == 0) return 0; return 1; } int Set::operator == (Set& b) { int n = count; if (n != b.count) return 0; if (n == 0) return 1; Pix i = first(); Pix j = b.first(); while (n-- > 0) { if ((b.seek((*this)(i)) == 0) || (seek(b(j)) == 0)) return 0; next(i); b.next(j); } return 1; } int Set::operator != (Set& b) { return !(*this == b); } void Set::operator |= (Set& b) { if (&b != this) for (Pix i = b.first(); i; b.next(i)) add(b(i)); } void Set::operator -= (Set& b) { if (&b == this) clear(); else for (Pix i = b.first(); i; b.next(i)) del(b(i)); } void Set::operator &= (Set& b) { if (&b != this) { Pix i = first(); Pix n = i; while (i != 0) { next(n); if (b.seek((*this)(i)) == 0) del((*this)(i)); i = n; } } } void Set::error(const char* msg) { (*lib_error_handler)("Set", msg); } Set& b) { if (&b != this) for (Pix i = b.first(); i; b.next(i)) add(b(i)); } libg++/g++-include/Set.hP 644 473 0 4603 4677677743 10205 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Set_h #pragma once #define _Set_h 1 #include #include ".defs.h" class Set { protected: int count; public: int length(); // current number of items int empty(); virtual Pix add( item) = 0; // add item; return Pix virtual void del( item) = 0; // delete item virtual int contains( item); // is item in set? virtual void clear(); // delete all items virtual Pix first() = 0; // Pix of first item or 0 virtual void next(Pix& i) = 0; // advance to next or 0 virtual & operator () (Pix i) = 0; // access item at i virtual int owns(Pix i); // is i a valid Pix ? virtual Pix seek( item); // Pix of item void operator |= (Set& b); // add all items in b void operator -= (Set& b); // delete items also in b void operator &= (Set& b); // delete items not in b int operator == (Set& b); int operator != (Set& b); int operator <= (Set& b); void error(const char* msg); virtual int OK() = 0; // rep invariant }; inline int Set::length() { return count; } inline int Set::empty() { return count == 0; } #endif operator -= (Set& b); // delete items also in b void operator &= (Set& b); // delete items nlibg++/g++-include/SplayBag.ccP 644 473 0 20336 4677677743 11333 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include ".SplayBag.h" /* struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985 splay tree algorithms All routines use a version of their `simple top-down' splay alg. (p 669) */ struct _dummySplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; } _dummy_null; /* traversal primitives */ SplayNode* SplayBag::leftmost() { SplayNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } SplayNode* SplayBag::rightmost() { SplayNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } SplayNode* SplayBag::succ(SplayNode* t) { if (t == 0) return 0; if (t->rt != 0) { t = t->rt; while (t->lt != 0) t = t->lt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->lt) return t->par; else t = t->par; } } } SplayNode* SplayBag::pred(SplayNode* t) { if (t == 0) return 0; else if (t->lt != 0) { t = t->lt; while (t->rt != 0) t = t->rt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->rt) return t->par; else t = t->par; } } } Pix SplayBag::seek( key, Pix i = 0) { if (root == 0) return 0; SplayNode* t = (SplayNode*) i; if (t != 0) { int cmp = CMP(key, t->item); if (cmp == 0) { t = succ(t); if (t != 0 && EQ(key, t->item)) return Pix(t); else return 0; } else if (cmp < 0) return 0; } t = root; int comp = CMP(key, t->item); if (comp == 0) return Pix(t); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) break; else { comp = CMP(key, tr->item); if (comp <= 0 || tr->rt == 0) { l->rt = t; t->par = l; l = t; t = tr; if (comp >= 0) break; } else { if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = tr->rt; comp = CMP(key, t->item); } } } else { SplayNode* tl = t->lt; if (tl == 0) break; else { comp = CMP(key, tl->item); if (comp >= 0 || tl->lt == 0) { r->lt = t; t->par = r; r = t; t = tl; if (comp <= 0) break; } else { if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tl->lt; comp = CMP(key, t->item); } } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; if (comp != 0) return 0; else { l = pred(t); while (l != 0 && EQ(l->item, key)) { t = l; l = pred(l); } return Pix(t); } } int SplayBag::nof( item) { int n = 0; SplayNode* t = (SplayNode*)(seek(item)); if (t != 0) { do { ++n; t = succ(t); } while (t != 0 && EQ(item, t->item)); } return n; } Pix SplayBag::add( item) { ++count; SplayNode* newnode = new SplayNode(item); SplayNode* t = root; if (t == 0) { root = newnode; return Pix(root); } int comp = CMP(item, t->item); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; int done = 0; while (!done) { if (comp >= 0) { SplayNode* tr = t->rt; if (tr == 0) { tr = newnode; comp = 0; done = 1; } else comp = CMP(item, tr->item); if (comp <= 0) { l->rt = t; t->par = l; l = t; t = tr; } else { SplayNode* trr = tr->rt; if (trr == 0) { trr = newnode; comp = 0; done = 1; } else comp = CMP(item, trr->item); if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = trr; } } else { SplayNode* tl = t->lt; if (tl == 0) { tl = newnode; comp = 0; done = 1; } else comp = CMP(item, tl->item); if (comp >= 0) { r->lt = t; t->par = r; r = t; t = tl; } else { SplayNode* tll = tl->lt; if (tll == 0) { tll = newnode; comp = 0; done = 1; } else comp = CMP(item, tll->item); if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tll; } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return Pix(root); } void SplayBag::_del(SplayNode* t) { if (t == 0) return; SplayNode* p = t->par; --count; if (t->rt == 0) { if (t == root) { if ((root = t->lt) != 0) root->par = 0; } else if (t == p->lt) { if ((p->lt = t->lt) != 0) p->lt->par = p; } else if ((p->rt = t->lt) != 0) p->rt->par = p; } else { SplayNode* r = t->rt; SplayNode* l = r->lt; for(;;) { if (l == 0) { if (t == root) { root = r; r->par = 0; } else if (t == p->lt) { p->lt = r; r->par = p; } else { p->rt = r; r->par = p; } if ((r->lt = t->lt) != 0) r->lt->par = r; break; } else { if ((r->lt = l->rt) != 0) r->lt->par = r; l->rt = r; r->par = l; r = l; l = l->lt; } } } delete t; } void SplayBag::remove( key) { SplayNode* t = (SplayNode*)(seek(key)); while (t != 0) { _del(t); t = (SplayNode*)(seek(key)); } } void SplayBag::_kill(SplayNode* t) { if (t != 0) { _kill(t->lt); _kill(t->rt); delete t; } } SplayNode* SplayBag::_copy(SplayNode* t) { if (t != 0) { SplayNode* l = _copy(t->lt); SplayNode* r = _copy(t->rt); SplayNode* x = new SplayNode(t->item, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayBag::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) <= 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } x = new SplayNode(t->item, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayBag::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNodlibg++/g++-include/SplayBag.hP 644 473 0 6307 4677677743 11157 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SplayBag_h #pragma once #define _SplayBag_h 1 #include ".Bag.h" #ifndef _SplayNode #define _SplayNode 1 struct SplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; item; SplayNode( h, SplayNode* l=0, SplayNode* r=0); ~SplayNode(); }; inline SplayNode::SplayNode( h, SplayNode* l=0, SplayNode* r=0) { item = h; lt = l; rt = r; par = 0; } inline SplayNode::~SplayNode() {} typedef SplayNode* SplayNodePtr; #endif class SplayBag : public Bag { protected: SplayNode* root; SplayNode* leftmost(); SplayNode* rightmost(); SplayNode* pred(SplayNode* t); SplayNode* succ(SplayNode* t); void _kill(SplayNode* t); SplayNode* _copy(SplayNode* t); void _del(SplayNode* t); public: SplayBag(); SplayBag(SplayBag& a); ~SplayBag(); Pix add( item); void del( item); void remove(item); int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item, Pix from = 0); Pix last(); void prev(Pix& i); int OK(); }; inline SplayBag::~SplayBag() { _kill(root); } inline SplayBag::SplayBag() { root = 0; count = 0; } inline SplayBag::SplayBag(SplayBag& b) { count = b.count; root = _copy(b.root); } inline Pix SplayBag::first() { return Pix(leftmost()); } inline Pix SplayBag::last() { return Pix(rightmost()); } inline void SplayBag::next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplayBag::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayBag::operator () (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline void SplayBag::clear() { _kill(root); count = 0; root = 0; } inline int SplayBag::contains( key) { return seek(key) != 0; } inline void SplayBag::del( key) { _del((SplayNode*)(seek(key))); } #endif :next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplayBag::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayBag::operator () (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline void SplayBag::clear() { _klibg++/g++-include/SplayMap.ccP 644 473 0 17453 4677677744 11366 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include "..SplayMap.h" /* struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985 splay tree algorithms All routines use a version of their `simple top-down' splay alg. (p 669) */ struct _dummySplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; } _dummy_null; /* traversal primitives */ SplayNode* SplayMap::leftmost() { SplayNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } SplayNode* SplayMap::rightmost() { SplayNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } SplayNode* SplayMap::succ(SplayNode* t) { if (t == 0) return 0; if (t->rt != 0) { t = t->rt; while (t->lt != 0) t = t->lt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->lt) return t->par; else t = t->par; } } } SplayNode* SplayMap::pred(SplayNode* t) { if (t == 0) return 0; else if (t->lt != 0) { t = t->lt; while (t->rt != 0) t = t->rt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->rt) return t->par; else t = t->par; } } } Pix SplayMap::seek( key) { SplayNode* t = root; if (t == 0) return 0; int comp = CMP(key, t->item); if (comp == 0) return Pix(t); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) break; else { comp = CMP(key, tr->item); if (comp <= 0 || tr->rt == 0) { l->rt = t; t->par = l; l = t; t = tr; if (comp >= 0) break; } else { if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = tr->rt; comp = CMP(key, t->item); } } } else { SplayNode* tl = t->lt; if (tl == 0) break; else { comp = CMP(key, tl->item); if (comp >= 0 || tl->lt == 0) { r->lt = t; t->par = r; r = t; t = tl; if (comp <= 0) break; } else { if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tl->lt; comp = CMP(key, t->item); } } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return (comp == 0) ? Pix(t) : 0; } & SplayMap::operator [] ( item) { SplayNode* t = root; if (t == 0) { ++count; root = new SplayNode(item, def); return root->cont; } int comp = CMP(item, t->item); if (comp == 0) return t->cont; SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) { ++count; tr = new SplayNode(item, def); comp = 0; } else comp = CMP(item, tr->item); if (comp <= 0) { l->rt = t; t->par = l; l = t; t = tr; } else { SplayNode* trr = tr->rt; if (trr == 0) { ++count; trr = new SplayNode(item, def); comp = 0; } else comp = CMP(item, trr->item); if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = trr; } } else { SplayNode* tl = t->lt; if (tl == 0) { ++count; tl = new SplayNode(item, def); comp = 0; } else comp = CMP(item, tl->item); if (comp >= 0) { r->lt = t; t->par = r; r = t; t = tl; } else { SplayNode* tll = tl->lt; if (tll == 0) { ++count; tll = new SplayNode(item, def); comp = 0; } else comp = CMP(item, tll->item); if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tll; } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return root->cont; } void SplayMap::del( key) { SplayNode* t = (SplayNode*)(seek(key)); if (t == 0) return; SplayNode* p = t->par; --count; if (t->rt == 0) { if (t == root) { if ((root = t->lt) != 0) root->par = 0; } else if (t == p->lt) { if ((p->lt = t->lt) != 0) p->lt->par = p; } else if ((p->rt = t->lt) != 0) p->rt->par = p; } else { SplayNode* r = t->rt; SplayNode* l = r->lt; for(;;) { if (l == 0) { if (t == root) { root = r; r->par = 0; } else if (t == p->lt) { p->lt = r; r->par = p; } else { p->rt = r; r->par = p; } if ((r->lt = t->lt) != 0) r->lt->par = r; break; } else { if ((r->lt = l->rt) != 0) r->lt->par = r; l->rt = r; r->par = l; r = l; l = l->lt; } } } delete t; } void SplayMap::_kill(SplayNode* t) { if (t != 0) { _kill(t->lt); _kill(t->rt); delete t; } } SplayNode* SplayMap::_copy(SplayNode* t) { if (t != 0) { SplayNode* l = _copy(t->lt); SplayNode* r = _copy(t->rt); SplayNode* x = new SplayNode(t->item, t->cont, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayMap::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } ode(t->item, t->cont, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } int SplayMap::OK() { int v = 1; if (root == 0) v = count == 0; elselibg++/g++-include/SplayMap.hP 644 473 0 7027 4677677744 11204 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SplayMap_h #pragma once #define _SplayMap_h 1 #include "..Map.h" #ifndef _SplayNode #define _SplayNode 1 struct SplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; item; cont; SplayNode( h, c, SplayNode* l=0, SplayNode* r=0); ~SplayNode(); }; inline SplayNode::SplayNode( h, c, SplayNode* l=0, SplayNode* r=0) :item(h), cont(c), lt(l), rt(r) { par = 0; } inline SplayNode::~SplayNode() {} typedef SplayNode* SplayNodePtr; #endif class SplayMap : public Map { protected: SplayNode* root; SplayNode* leftmost(); SplayNode* rightmost(); SplayNode* pred(SplayNode* t); SplayNode* succ(SplayNode* t); void _kill(SplayNode* t); SplayNode* _copy(SplayNode* t); public: SplayMap( dflt); SplayMap(SplayMap& a); ~SplayMap(); & operator [] ( key); void del( key); Pix first(); void next(Pix& i); & key(Pix i); & contents(Pix i); Pix seek( key); int contains( key); void clear(); Pix last(); void prev(Pix& i); int OK(); }; inline SplayMap::~SplayMap() { _kill(root); } inline SplayMap::SplayMap( dflt) :(dflt) { root = 0; } inline SplayMap::SplayMap(SplayMap& b) :(b.def) { count = b.count; root = _copy(b.root); } inline Pix SplayMap::first() { return Pix(leftmost()); } inline Pix SplayMap::last() { return Pix(rightmost()); } inline void SplayMap::next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplayMap::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayMap::key (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline & SplayMap::contents (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->cont; } inline void SplayMap::clear() { _kill(root); count = 0; root = 0; } inline int SplayMap::contains( key) { return seek(key) != 0; } #endif Node*)i)); } inline void SplayMap::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayMap::key (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline & SplayMap::contents (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->cont; } inline void SplayMap::clear() { _kill(root); count = 0; root = 0; } inline int SplayMap::contains( key) { return seeklibg++/g++-include/streambuf.h 644 473 0 12004 4677677744 11335 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _streambuf_h #pragma once #define _streambuf_h 1 /* streambufs. basic streambufs and filebufs are as in Stroustrup, ch 8, but the base class contains virtual extensions that allow most capabilities of libg++ Files to be used as streambufs via `Filebufs'. */ #include #include #include // see below for NO_LINE_BUFFER_STREAMBUFS #ifndef BUFSIZE #ifdef BUFSIZ #define BUFSIZE BUFSIZ #else #define BUFSIZE 1024 #endif #endif enum open_mode // filebuf open modes { input=0, output=1, append=2 }; class streambuf { public: char* base; // start of buffer char* pptr; // put-pointer (and gptr fence) char* gptr; // get-pointer char* eptr; // last valid addr in buffer char alloc; // true if we own freestore alloced buffer streambuf(); streambuf(char* buf, int buflen); virtual ~streambuf(); int doallocate(); int allocate(); int must_overflow(int ch); // true if should call overflow virtual int overflow(int c = EOF); // flush -- return EOF if fail virtual int underflow(); // fill -- return EOF if fail int sgetc(); // get one char (as int) or EOF int snextc(); // get and advance void stossc(); // advance only int sputback(char); // unget int sputc(int c = EOF); // write one char virtual streambuf* setbuf(char* buf, int buflen, int preloaded_count = 0); // (not virtual in AT&T) // the following aren't in AT&T version: int sputs(const char* s); // write null-terminated str int sputsn(const char* s, int len); // write len bytes virtual const char* name(); virtual streambuf* open(const char* name, open_mode m); virtual streambuf* open(const char* filename, io_mode m, access_mode a); virtual streambuf* open(const char* filename, const char* m); virtual streambuf* open(int filedesc, io_mode m); virtual streambuf* open(FILE* fileptr); virtual int is_open(); virtual int close(); virtual void error(); }; class filebuf: public streambuf { public: int fd; char opened; int overflow(int c = EOF); int underflow(); filebuf(); filebuf(int newfd); filebuf(int newfd, char* buf, int buflen); ~filebuf(); streambuf* open(const char* name, open_mode m); int is_open(); int close(); }; class Filebuf: public streambuf // libg++ File version { public: File* Fp; void init_streambuf_ptrs(); int overflow(int c = EOF); int underflow(); Filebuf(); Filebuf(const char* filename, io_mode m, access_mode a); Filebuf(const char* filename, const char* m); Filebuf(int filedesc, io_mode m); Filebuf(FILE* fileptr); ~Filebuf(); const char* name(); streambuf* setbuf(char* buf, int buflen, int preloaded_count = 0); streambuf* open(const char* filename, io_mode m, access_mode a); streambuf* open(const char* filename, const char* m); streambuf* open(int filedesc, io_mode m); streambuf* open(FILE* fileptr); int is_open(); int close(); void error(); }; inline int streambuf::must_overflow(int ch) { #ifndef NO_LINE_BUFFER_STREAMBUF return pptr >= eptr || ch == '\n'; #else return pptr >= eptr; #endif } inline int streambuf::allocate() { return (base == 0)? doallocate() : 0; } inline int streambuf::sgetc() { return (gptr >= pptr)? underflow() : int(*gptr); } inline int streambuf::snextc() { ++gptr; return (gptr >= pptr)? underflow() : int(*gptr); } inline void streambuf::stossc() { if (gptr >= pptr) underflow(); else gptr++; } inline int streambuf::sputback(char ch) { return (gptr > base)? (*--gptr = ch) : EOF; } inline int streambuf::sputc(int ch) { return must_overflow(ch)? overflow(ch) : (*pptr++ = char(ch)); } #endif rn (base == 0)? doallocate() : 0; } inline int streambuf::sgetc() { return (gptr >= pptr)? underflow() : int(*gptr); } inline int streambuf::snextc() { ++gptr; return (gptr >= pptr)? underflow() : int(*gptr); } inline void streambuf::stossc() { if (gptr >= pptr) underflow(); else gptr++; } inline int streambuf::sputback(char ch) { return (gptr > base)? (*--gptr = ch) : EOF; } inline int streambuf::sputc(int ch) { return must_overflow(ch)? overflow(ch) : (*pptr++ = char(ch)); } #enlibg++/g++-include/SplayPQ.hP 644 473 0 6132 4677677744 11003 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SplayPQ_h #pragma once #define _SplayPQ_h 1 #include ".PQ.h" #ifndef _SplayNode #define _SplayNode 1 struct SplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; item; SplayNode( h, SplayNode* l=0, SplayNode* r=0); ~SplayNode(); }; inline SplayNode::SplayNode( h, SplayNode* l=0, SplayNode* r=0) { item = h; lt = l; rt = r; par = 0; } inline SplayNode::~SplayNode() {} typedef SplayNode* SplayNodePtr; #endif class SplayPQ : public PQ { protected: SplayNode* root; SplayNode* leftmost(); SplayNode* rightmost(); SplayNode* pred(SplayNode* t); SplayNode* succ(SplayNode* t); void _kill(SplayNode* t); SplayNode* _copy(SplayNode* t); public: SplayPQ(); SplayPQ(SplayPQ& a); ~SplayPQ(); Pix enq( item); deq(); & front(); void del_front(); int contains( item); void clear(); Pix first(); Pix last(); void next(Pix& i); void prev(Pix& i); & operator () (Pix i); void del(Pix i); Pix seek( item); int OK(); // rep invariant }; inline SplayPQ::~SplayPQ() { _kill(root); } inline SplayPQ::SplayPQ() { root = 0; count = 0; } inline SplayPQ::SplayPQ(SplayPQ& b) { count = b.count; root = _copy(b.root); } inline Pix SplayPQ::first() { return Pix(leftmost()); } inline Pix SplayPQ::last() { return Pix(rightmost()); } inline void SplayPQ::next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplayPQ::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayPQ::operator () (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline void SplayPQ::clear() { _kill(root); count = 0; root = 0; } inline int SplayPQ::contains( key) { return seek(key) != 0; } #endif line Pix SplayPQ::last() { return Pix(rightmost()); } inline void SplayPQ::next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplayPQ::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplayPQ::operator () (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline void SplayPQ::clear() { _kill(root); count = 0; roolibg++/g++-include/SplaySet.ccP 644 473 0 22207 4677677744 11375 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include ".SplaySet.h" /* struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985 splay tree algorithms All routines use a version of their `simple top-down' splay alg. (p 669) */ struct _dummySplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; } _dummy_null; /* traversal primitives */ SplayNode* SplaySet::leftmost() { SplayNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } SplayNode* SplaySet::rightmost() { SplayNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } SplayNode* SplaySet::succ(SplayNode* t) { if (t == 0) return 0; if (t->rt != 0) { t = t->rt; while (t->lt != 0) t = t->lt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->lt) return t->par; else t = t->par; } } } SplayNode* SplaySet::pred(SplayNode* t) { if (t == 0) return 0; else if (t->lt != 0) { t = t->lt; while (t->rt != 0) t = t->rt; return t; } else { for (;;) { if (t->par == 0 || t == t->par->rt) return t->par; else t = t->par; } } } Pix SplaySet::seek( key) { SplayNode* t = root; if (t == 0) return 0; int comp = CMP(key, t->item); if (comp == 0) return Pix(t); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) break; else { comp = CMP(key, tr->item); if (comp <= 0 || tr->rt == 0) { l->rt = t; t->par = l; l = t; t = tr; if (comp >= 0) break; } else { if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = tr->rt; comp = CMP(key, t->item); } } } else { SplayNode* tl = t->lt; if (tl == 0) break; else { comp = CMP(key, tl->item); if (comp >= 0 || tl->lt == 0) { r->lt = t; t->par = r; r = t; t = tl; if (comp <= 0) break; } else { if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tl->lt; comp = CMP(key, t->item); } } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return (comp == 0) ? Pix(t) : 0; } Pix SplaySet::add( item) { SplayNode* t = root; if (t == 0) { ++count; root = new SplayNode(item); return Pix(root); } int comp = CMP(item, t->item); if (comp == 0) return Pix(t); SplayNode* dummy = (SplayNode*)(&_dummy_null); SplayNode* l = dummy; SplayNode* r = dummy; dummy->rt = dummy->lt = dummy->par = 0; while (comp != 0) { if (comp > 0) { SplayNode* tr = t->rt; if (tr == 0) { ++count; tr = new SplayNode(item); comp = 0; } else comp = CMP(item, tr->item); if (comp <= 0) { l->rt = t; t->par = l; l = t; t = tr; } else { SplayNode* trr = tr->rt; if (trr == 0) { ++count; trr = new SplayNode(item); comp = 0; } else comp = CMP(item, trr->item); if ((t->rt = tr->lt) != 0) t->rt->par = t; tr->lt = t; t->par = tr; l->rt = tr; tr->par = l; l = tr; t = trr; } } else { SplayNode* tl = t->lt; if (tl == 0) { ++count; tl = new SplayNode(item); comp = 0; } else comp = CMP(item, tl->item); if (comp >= 0) { r->lt = t; t->par = r; r = t; t = tl; } else { SplayNode* tll = tl->lt; if (tll == 0) { ++count; tll = new SplayNode(item); comp = 0; } else comp = CMP(item, tll->item); if ((t->lt = tl->rt) != 0) t->lt->par = t; tl->rt = t; t->par = tl; r->lt = tl; tl->par = r; r = tl; t = tll; } } } if ((r->lt = t->rt) != 0) r->lt->par = r; if ((l->rt = t->lt) != 0) l->rt->par = l; if ((t->lt = dummy->rt) != 0) t->lt->par = t; if ((t->rt = dummy->lt) != 0) t->rt->par = t; t->par = 0; root = t; return Pix(root); } void SplaySet::del( key) { SplayNode* t = (SplayNode*)(seek(key)); if (t == 0) return; SplayNode* p = t->par; --count; if (t->rt == 0) { if (t == root) { if ((root = t->lt) != 0) root->par = 0; } else if (t == p->lt) { if ((p->lt = t->lt) != 0) p->lt->par = p; } else if ((p->rt = t->lt) != 0) p->rt->par = p; } else { SplayNode* r = t->rt; SplayNode* l = r->lt; for(;;) { if (l == 0) { if (t == root) { root = r; r->par = 0; } else if (t == p->lt) { p->lt = r; r->par = p; } else { p->rt = r; r->par = p; } if ((r->lt = t->lt) != 0) r->lt->par = r; break; } else { if ((r->lt = l->rt) != 0) r->lt->par = r; l->rt = r; r->par = l; r = l; l = l->lt; } } } delete t; } void SplaySet::_kill(SplayNode* t) { if (t != 0) { _kill(t->lt); _kill(t->rt); delete t; } } SplayNode* SplaySet::_copy(SplayNode* t) { if (t != 0) { SplayNode* l = _copy(t->lt); SplayNode* r = _copy(t->rt); SplayNode* x = new SplayNode(t->item, l, r); if (l != 0) l->par = x; if (r != 0) r->par = x; return x; } else return 0; } /* relationals */ int SplaySet::operator == (SplaySet& y) { if (count != y.count) return 0; else { SplayNode* t = leftmost(); SplayNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (!EQ(t->item, u->item)) return 0; else { t = succ(t); u = y.succ(u); } } } } int SplaySet::operator <= (SplaySet& y) { if (count > y.count) return 0; else { SplayNode* t = leftmost(); SplayNode* u = y.leftmost(); for (;;) { if (t == 0) return 1; else if (u == 0) return 0; int cmp = CMP(t->item, u->item); if (cmp == 0) { t = succ(t); u = y.succ(u); } else if (cmp < 0) return 0; else u = y.succ(u); } } } void SplaySet::operator |=(SplaySet& y) { if (&y == this) return; SplayNode* u = y.leftmost(); while (u != 0) { add(u->item); u = y.succ(u); } } void SplaySet::operator &= (SplaySet& y) { if (y.count == 0) clear(); else if (&y != this && count != 0) { SplayNode* t = leftmost(); while (t != 0) { SplayNode* s = succ(t); if (y.seek(t->item) == 0) del(t->item); t = s; } } } void SplaySet::operator -=(SplaySet& y) { if (&y == this) clear(); else if (y.count != 0) { SplayNode* t = leftmost(); while (t != 0) { SplayNode* s = succ(t); if (y.seek(t->item) != 0) del(t->item); t = s; } } } int SplaySet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } most(); while (t != 0) { SplayNode* s = succ(t); if (y.seek(t->item) != 0) del(t->item); t = s; } } } int SplaySet::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; SplayNode* trail = leftmost(); SplayNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->itemlibg++/g++-include/SplaySet.hP 644 473 0 6614 4677677745 11224 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _SplaySet_h #pragma once #define _SplaySet_h 1 #include ".Set.h" #ifndef _SplayNode #define _SplayNode 1 struct SplayNode { SplayNode* lt; SplayNode* rt; SplayNode* par; item; SplayNode( h, SplayNode* l=0, SplayNode* r=0); ~SplayNode(); }; inline SplayNode::SplayNode( h, SplayNode* l=0, SplayNode* r=0) { item = h; lt = l; rt = r; par = 0; } inline SplayNode::~SplayNode() {} typedef SplayNode* SplayNodePtr; #endif class SplaySet : public Set { protected: SplayNode* root; SplayNode* leftmost(); SplayNode* rightmost(); SplayNode* pred(SplayNode* t); SplayNode* succ(SplayNode* t); void _kill(SplayNode* t); SplayNode* _copy(SplayNode* t); public: SplaySet(); SplaySet(SplaySet& a); ~SplaySet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item); Pix last(); void prev(Pix& i); void operator |= (SplaySet& b); void operator -= (SplaySet& b); void operator &= (SplaySet& b); int operator == (SplaySet& b); int operator != (SplaySet& b); int operator <= (SplaySet& b); int OK(); }; inline SplaySet::~SplaySet() { _kill(root); } inline SplaySet::SplaySet() { root = 0; count = 0; } inline SplaySet::SplaySet(SplaySet& b) { count = b.count; root = _copy(b.root); } inline int SplaySet::operator != (SplaySet& b) { return ! (*this == b); } inline Pix SplaySet::first() { return Pix(leftmost()); } inline Pix SplaySet::last() { return Pix(rightmost()); } inline void SplaySet::next(Pix& i) { if (i != 0) i = Pix(succ((SplayNode*)i)); } inline void SplaySet::prev(Pix& i) { if (i != 0) i = Pix(pred((SplayNode*)i)); } inline & SplaySet::operator () (Pix i) { if (i == 0) error("null Pix"); return ((SplayNode*)i)->item; } inline void SplaySet::clear() { _kill(root); count = 0; root = 0; } inline int SplaySet::contains( key) { return seek(key) != 0; } #endif ix SplaySet::last() { return Pix(rightmost()); } inline void SplaySet::next(Pix& i) { if (i != 0) i = Pixlibg++/g++-include/new.h 644 473 0 1345 4677677745 10125 #ifndef _new_h #pragma once #define _new_h 1 #include #include #ifndef NO_LIBGXX_MALLOC #define MALLOC_ALIGN_MASK 7 /* ptrs aligned at 8 byte boundaries */ #define MALLOC_MIN_OVERHEAD 8 /* 8 bytes of overhead per pointer */ #endif typedef void (*new_handler_t)(); extern "C" void default_new_handler(); extern "C" new_handler_t set_new_handler(new_handler_t); #ifdef __GNUG__ #define NEW(where) new { where } #endif // default placement version of operator new static inline void *operator new(size_t, void *place) { return place; } // provide a C++ interface to vector-resize via realloc static inline void *operator new(size_t size, void *ptr, size_t new_len) { return realloc(ptr, new_len * size); } #endif ad per pointer */ #endif typedef void (*new_handler_t)(); extern "C" void default_new_handler(); extern "C" new_handler_t set_new_handler(new_handler_t); #ifdef __GNUG__ #define NEW(where) new { where } #endif // default placement version of operator new static inline void *operalibg++/g++-include/Stack.hP 644 473 0 3237 4677677745 10523 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Stack_h #pragma once #define _Stack_h #include #include ".defs.h" class Stack { public: Stack(); ~Stack(); virtual void push( item) = 0; virtual pop() = 0; virtual & top() = 0; virtual void del_top() = 0; virtual int empty() = 0; virtual int full() = 0; virtual int length() = 0; virtual void clear() = 0; void error(const char*); virtual int OK() = 0; }; inline Stack::Stack() {} inline Stack::~Stack() {} inline void Stack::error(const char* msg) { (*lib_error_handler)("Stack", msg); } #endif rtual pop() = 0; virtual & top() = 0; virtual void del_top() = 0; virtual int empty() = 0; virtual int full() = 0; virtual int length() = 0; virtual void clear() = 0; void error(const char*); virtual int OK() = 0; }; libg++/g++-include/VHBag.ccP 644 473 0 14152 4677677745 10561 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".VHBag.h" /* codes for status fields */ #define EMPTYCELL 0 #define VALIDCELL 1 #define DELETEDCELL 2 VHBag::VHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY) { tab = new [size = sz]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; } VHBag::VHBag(VHBag& a) { tab = new [size = a.size]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (Pix p = a.first(); p; a.next(p)) add(a(p)); } /* * hashing method: double hash based on high bits of hash fct, * followed by linear probe. Can't do too much better if table * sizes not constrained to be prime. */ static inline unsigned int doublehashinc(unsigned int h, unsigned int s) { return ((h / s) % s) >? 1; } Pix VHBag::seek( key, Pix p = 0) { * t = (*) p; if (t == 0 || !EQ(*t, key)) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return 0; else if (status[h] == VALIDCELL && EQ(key, tab[h])) return Pix(&tab[h]); if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } return 0; } else { int seent = 0; unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return 0; else if (&tab[h] == t) seent = 1; else if (seent && status[h] == VALIDCELL && EQ(key, tab[h])) return Pix(&tab[h]); if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } return 0; } } int VHBag::nof( item) { int n = 0; unsigned int hashval = HASH(item); unsigned int h = hashval % size; unsigned int firsth = size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return n; else if (h != firsth && status[h] == VALIDCELL && EQ(item, tab[h])) { ++n; if (firsth >= size) firsth = h; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } return n; } Pix VHBag::add( item) { if (size <= count + 1) resize(); unsigned int bestspot = size; unsigned int hashval = HASH(item); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) { if (bestspot >= size) bestspot = h; tab[bestspot] = item; status[bestspot] = VALIDCELL; ++count; return Pix(&tab[bestspot]); } else if (status[h] == DELETEDCELL) { if (bestspot >= size) bestspot = h; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } tab[bestspot] = item; status[bestspot] = VALIDCELL; ++count; return Pix(&tab[bestspot]); } void VHBag::del( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return; else if (status[h] == VALIDCELL && EQ(key, tab[h])) { status[h] = DELETEDCELL; --count; return; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } } void VHBag::remove( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return; else if (status[h] == VALIDCELL && EQ(key, tab[h])) { status[h] = DELETEDCELL; --count; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } } void VHBag::clear() { for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; } void VHBag::resize(unsigned int newsize = 0) { if (newsize <= count) { newsize = DEFAULT_INITIAL_CAPACITY; while (newsize <= count) newsize <<= 1; } * oldtab = tab; char* oldstatus = status; unsigned int oldsize = size; tab = new [size = newsize]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]); delete [oldsize] oldtab; delete oldstatus; } Pix VHBag::first() { for (unsigned int pos = 0; pos < size; ++pos) if (status[pos] == VALIDCELL) return Pix(&tab[pos]); return 0; } void VHBag::next(Pix& i) { if (i == 0) return; unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; pos < size; ++pos) if (status[pos] == VALIDCELL) { i = Pix(&tab[pos]); return; } i = 0; } int VHBag::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL) v = 0; } v &= n == count; if (!v) error("invariant failure"); return v; } ; unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; pos < size; ++pos) if (status[pos] == VALIDCELL) { i = Pix(&tab[pos]); return; } i = 0; } int VHBag::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; else if (status[i] != DELETEDCELL && statuslibg++/g++-include/VHBag.hP 644 473 0 3740 4677677745 10404 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VHBag_h #pragma once #define _VHBag_h 1 #include ".Bag.h" class VHBag : public Bag { protected: * tab; char* status; unsigned int size; public: VHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY); VHBag(VHBag& a); ~VHBag(); Pix add( item); void del( item); void remove(item); int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item, Pix from = 0); int capacity(); void resize(unsigned int newsize = 0); int OK(); }; inline VHBag::~VHBag() { delete [size] tab; delete status; } inline int VHBag::capacity() { return size; } inline int VHBag::contains( key) { return seek(key) != 0; } inline & VHBag::operator () (Pix i) { if (i == 0) error("null Pix"); return *((*)i); } #endif next(Pix& i); & libg++/g++-include/VHMap.ccP 644 473 0 11657 4677677745 10614 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include "..VHMap.h" /* codes for status fields */ #define EMPTYCELL 0 #define VALIDCELL 1 #define DELETEDCELL 2 VHMap::VHMap( dflt, unsigned int sz = DEFAULT_INITIAL_CAPACITY) :(dflt) { tab = new [size = sz]; cont = new [size]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; } VHMap::VHMap(VHMap& a) : (a.def) { tab = new [size = a.size]; cont = new [size]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p); } /* * hashing method: double hash based on high bits of hash fct, * followed by linear probe. Can't do too much better if table * sizes not constrained to be prime. */ static inline unsigned int doublehashinc(unsigned int h, unsigned int s) { return ((h / s) % s) >? 1; } Pix VHMap::seek( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return 0; else if (status[h] == VALIDCELL && EQ(key, tab[h])) return Pix(&tab[h]); if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } return 0; } & VHMap::operator []( item) { if (size <= count + 1) resize(); unsigned int bestspot = size; unsigned int hashval = HASH(item); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) { ++count; if (bestspot >= size) bestspot = h; tab[bestspot] = item; status[bestspot] = VALIDCELL; cont[bestspot] = def; return cont[bestspot]; } else if (status[h] == DELETEDCELL) { if (bestspot >= size) bestspot = h; } else if (EQ(tab[h],item)) return cont[h]; if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } ++count; status[bestspot] = VALIDCELL; tab[bestspot] = item; cont[bestspot] = def; return cont[bestspot]; } void VHMap::del( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return; else if (status[h] == VALIDCELL && EQ(key, tab[h])) { status[h] = DELETEDCELL; --count; return; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } } void VHMap::clear() { for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; } void VHMap::resize(unsigned int newsize = 0) { if (newsize <= count) { newsize = DEFAULT_INITIAL_CAPACITY; while (newsize <= count) newsize <<= 1; } * oldtab = tab; * oldcont = cont; char* oldstatus = status; unsigned int oldsize = size; tab = new [size = newsize]; cont = new [size]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) (*this)[oldtab[i]] = oldcont[i]; delete [oldsize] oldtab; delete [oldsize] oldcont; delete oldstatus; } Pix VHMap::first() { for (unsigned int pos = 0; pos < size; ++pos) if (status[pos] == VALIDCELL) return Pix(&tab[pos]); return 0; } void VHMap::next(Pix& i) { if (i == 0) return; unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; pos < size; ++pos) if (status[pos] == VALIDCELL) { i = Pix(&tab[pos]); return; } i = 0; } int VHMap::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL) v = 0; } v &= n == count; if (!v) error("invariant failure"); return v; } unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; poslibg++/g++-include/VHMap.hP 644 473 0 4115 4677677746 10426 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VHMap_h #pragma once #define _VHMap_h 1 #include "..Map.h" class VHMap : public Map { protected: * tab; * cont; char* status; unsigned int size; public: VHMap( dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY); VHMap(VHMap& a); ~VHMap(); & operator [] ( key); void del( key); Pix first(); void next(Pix& i); & key(Pix i); & contents(Pix i); Pix seek( key); int contains( key); void clear(); void resize(unsigned int newsize = 0); int OK(); }; inline VHMap::~VHMap() { delete [size] tab; delete [size] cont; delete [size] status; } inline int VHMap::contains( key) { return seek(key) != 0; } inline & VHMap::key(Pix i) { if (i == 0) error("null Pix"); return *((*)i); } inline & VHMap::contents(Pix i) { if (i == 0) error("null Pix"); return cont[((unsigned)(i) - (unsigned)(tab)) / sizeof()]; } #endif ear(); void resize(unsigned int newsize = 0); int OK(); }; inline VHMap::~VHMap() { delete [size] tab; delete [size] cont; delete [size] status; } inline int VHMap::contains( key) { return seek(key) != 0; } inline & VHMap::key(Pix i) { if (i == 0) error("null Pix"); return *((*)i); } inline & VHMap::contents(Pix i) { if (i == 0) error("null Pix")libg++/g++-include/VHSet.ccP 644 473 0 13531 4677677746 10624 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".VHSet.h" /* codes for status fields */ #define EMPTYCELL 0 #define VALIDCELL 1 #define DELETEDCELL 2 VHSet::VHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY) { tab = new [size = sz]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; } VHSet::VHSet(VHSet& a) { tab = new [size = a.size]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (Pix p = a.first(); p; a.next(p)) add(a(p)); } /* * hashing method: double hash based on high bits of hash fct, * followed by linear probe. Can't do too much better if table * sizes not constrained to be prime. */ static inline unsigned int doublehashinc(unsigned int h, unsigned int s) { return ((h / s) % s) >? 1; } Pix VHSet::seek( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return 0; else if (status[h] == VALIDCELL && EQ(key, tab[h])) return Pix(&tab[h]); if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } return 0; } Pix VHSet::add( item) { if (size <= count + 1) resize(); unsigned int bestspot = size; unsigned int hashval = HASH(item); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) { if (bestspot >= size) bestspot = h; tab[bestspot] = item; status[bestspot] = VALIDCELL; ++count; return Pix(&tab[bestspot]); } else if (status[h] == DELETEDCELL) { if (bestspot >= size) bestspot = h; } else if (EQ(tab[h],item)) return Pix(&tab[h]); if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } tab[bestspot] = item; status[bestspot] = VALIDCELL; ++count; return Pix(&tab[bestspot]); } void VHSet::del( key) { unsigned int hashval = HASH(key); unsigned int h = hashval % size; for (unsigned int i = 0; i <= size; ++i) { if (status[h] == EMPTYCELL) return; else if (status[h] == VALIDCELL && EQ(key, tab[h])) { status[h] = DELETEDCELL; --count; return; } if (i == 0) h = (h + doublehashinc(hashval, size)) % size; else if (++h >= size) h -= size; } } void VHSet::clear() { for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; } void VHSet::resize(unsigned int newsize = 0) { if (newsize <= count) { newsize = DEFAULT_INITIAL_CAPACITY; while (newsize <= count) newsize <<= 1; } * oldtab = tab; char* oldstatus = status; unsigned int oldsize = size; tab = new [size = newsize]; status = new char[size]; for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = 0; for (i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]); delete [oldsize] oldtab; delete oldstatus; } Pix VHSet::first() { for (unsigned int pos = 0; pos < size; ++pos) if (status[pos] == VALIDCELL) return Pix(&tab[pos]); return 0; } void VHSet::next(Pix& i) { if (i == 0) return; unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; pos < size; ++pos) if (status[pos] == VALIDCELL) { i = Pix(&tab[pos]); return; } i = 0; } int VHSet:: operator == (VHSet& b) { if (count != b.count) return 0; else { for (unsigned int i = 0; i < size; ++i) if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) return 0; for (i = 0; i < b.size; ++i) if (b.status[i] == VALIDCELL && seek(b.tab[i]) == 0) return 0; return 1; } } int VHSet::operator <= (VHSet& b) { if (count > b.count) return 0; else { for (unsigned int i = 0; i < size; ++i) if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) return 0; return 1; } } void VHSet::operator |= (VHSet& b) { if (&b == this || b.count == 0) return; for (unsigned int i = 0; i < b.size; ++i) if (b.status[i] == VALIDCELL) add(b.tab[i]); } void VHSet::operator &= (VHSet& b) { if (&b == this || count == 0) return; for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) { status[i] = DELETEDCELL; --count; } } } void VHSet::operator -= (VHSet& b) { for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) { status[i] = DELETEDCELL; --count; } } } int VHSet::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL) v = 0; } v &= n == count; if (!v) error("invariant failure"); return v; } VHSet::operator -= (VHSet& b) { for (unsigned int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) { status[i] = DELETEDlibg++/g++-include/VHSet.hP 644 473 0 4346 4677677746 10452 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VHSet_h #pragma once #define _VHSet_h 1 #include ".Set.h" class VHSet : public Set { protected: * tab; char* status; unsigned int size; public: VHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY); VHSet(VHSet& a); ~VHSet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item); void operator |= (VHSet& b); void operator -= (VHSet& b); void operator &= (VHSet& b); int operator == (VHSet& b); int operator != (VHSet& b); int operator <= (VHSet& b); int capacity(); void resize(unsigned int newsize = 0); int OK(); }; inline VHSet::~VHSet() { delete [size] tab; delete status; } inline int VHSet::capacity() { return size; } inline int VHSet::contains( key) { return seek(key) != 0; } inline & VHSet::operator () (Pix i) { if (i == 0) error("null Pix"); return *((*)i); } inline int VHSet::operator != (VHSet& b) { return ! ((*this) == b); } #endif tor <= (VHSet& b); int capacity(); void resize(unsigned int newsize = 0); int OK(); }; inline VHSet::~VHSet() { delete [size] tab; delete status; } inline int VHSet::capacity() { return size; } inline int VHSet::containlibg++/g++-include/VOHSet.ccP 644 473 0 16233 4677677746 10745 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Doug Schmidt This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".VOHSet.h" /* codes for status fields */ #define EMPTYCELL 0 #define VALIDCELL 1 #define DELETEDCELL 2 VOHSet::VOHSet(int sz = DEFAULT_INITIAL_CAPACITY) { // The size of the hash table is always the smallest power of 2 >= the size // indicated by the user. This allows several optimizations, including // the use of actual double hashing and elimination of the mod instruction. size = 1; while (size < sz) size <<= 1; tab = new [size]; status = new char[size]; for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = cnt = 0; } VOHSet::VOHSet(VOHSet& a) { tab = new [size = a.size]; status = new char[size]; for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = cnt = 0; for (Pix p = a.first(); p; a.next(p)) add(a(p)); } Pix VOHSet::seek( key) { // Uses ordered double hashing to perform a search of the table. // This greatly speeds up the average-case time for an unsuccessful search. unsigned hashval = HASH(key); // We can avoid the mod operation since size is a power of 2. unsigned h = hashval & (size - 1); // The increment must be odd, since all odd numbers are relatively // prime to a power of 2!! unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1)); // There is always at least 1 empty cell, so this loop is guaranteed to halt! while (status[h] != EMPTYCELL) { int cmp = CMP (key, tab[h]); if (cmp == 0) { if (status[h] == VALIDCELL) return Pix(&tab[h]); else return 0; } else if (cmp > 0) return 0; else h = ((h + inc) & (size - 1)); } return 0; } // This adds an item if it doesn't already exist. By performing the initial // comparison we assure that the table always contains at least 1 empty // spot. This speeds up later searching by a constant factor. // The insertion algorithm uses ordered double hashing. See Standish's // 1980 ``Data Structure's Techniques'' book for details. Pix VOHSet::add( x) { if (size <= cnt+1) resize(); unsigned hashval = HASH(x); unsigned h = hashval & (size - 1); if (status[h] != VALIDCELL) // save some work if possible { if (status[h] == EMPTYCELL) cnt++; count++; tab[h] = x; status[h] = VALIDCELL; return Pix(&tab[h]); } int cmp = CMP(x, tab[h]); if (cmp == 0) return Pix(&tab[h]); item = x; Pix mypix = 0; unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1)); for (;;) { if (cmp < 0) { temp = tab[h]; tab[h] = item; item = temp; if (mypix == 0) mypix = Pix(&tab[h]); inc = ((((HASH(item) / size) << 1) + 1) & (size - 1)); h = ((h + inc) & (size - 1)); cmp = CMP(item, tab[h]); } else h = ((h + inc) & (size - 1)); if (status[h] != VALIDCELL) { if (status[h] == EMPTYCELL) cnt++; count++; tab[h] = item; status[h] = VALIDCELL; return (mypix == 0)? Pix(&tab[h]) : mypix; } } } void VOHSet::del( key) { // This performs a deletion by marking the item's status field. // Note that we only decrease the count, *not* the cnt, since this // would cause trouble for subsequent steps in the algorithm. See // Reingold and Hanson's ``Data Structure's'' book for a justification // of this approach. unsigned hashval = HASH(key); unsigned h = hashval & (size - 1); unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1)); while (status[h] != EMPTYCELL) { int cmp = CMP(key, tab[h]); if (cmp < 0) h = ((h + inc) & (size - 1)); else if (status[h] == VALIDCELL && cmp == 0) { status[h] = DELETEDCELL; count--; return; } else return; } } void VOHSet::clear() { for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = cnt = 0; } void VOHSet::resize(int newsize = 0) { if (newsize <= count) newsize = count; int s = 1; while (s <= newsize) s <<= 1; newsize = s; * oldtab = tab; char* oldstatus = status; int oldsize = size; tab = new [size = newsize]; status = new char[size]; for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; count = cnt = 0; for (i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]); delete [oldsize] oldtab; delete oldstatus; } Pix VOHSet::first() { for (int pos = 0; pos < size; ++pos) if (status[pos] == VALIDCELL) return Pix(&tab[pos]); return 0; } void VOHSet::next(Pix& i) { if (i == 0) return; int pos = ((unsigned)i - (unsigned)tab) / sizeof() + 1; for (; pos < size; ++pos) if (status[pos] == VALIDCELL) { i = Pix(&tab[pos]); return; } i = 0; } int VOHSet:: operator == (VOHSet& b) { if (count != b.count) return 0; else { for (int i = 0; i < size; ++i) if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) return 0; for (i = 0; i < b.size; ++i) if (b.status[i] == VALIDCELL && seek(b.tab[i]) == 0) return 0; return 1; } } int VOHSet:: operator != (VOHSet& b) { return !(*this == b); } int VOHSet::operator <= (VOHSet& b) { if (count > b.count) return 0; else { for (int i = 0; i < size; ++i) if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) return 0; return 1; } } void VOHSet::operator |= (VOHSet& b) { if (&b == this || b.count == 0) return; for (int i = 0; i < b.size; ++i) if (b.status[i] == VALIDCELL) add(b.tab[i]); } void VOHSet::operator &= (VOHSet& b) { if (&b == this || count == 0) return; for (int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) == 0) { status[i] = DELETEDCELL; --count; } } } void VOHSet::operator -= (VOHSet& b) { for (int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) { status[i] = DELETEDCELL; --count; } } } int VOHSet::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL) v = 0; } v &= n == count; if (!v) error("invariant failure"); return v; } void VOHSet::operator -= (VOHSet& b) { for (int i = 0; i < size; ++i) { if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) { status[i] = DELETEDCELL; --count; } } } int VOHSet::OK() { int v = tab != 0; v &= status != 0; int n = 0; for (int i = 0; i < size; ++i) { if (status[i] == VALIDCELL) ++n; libg++/g++-include/VOHSet.hP 644 473 0 4364 4677677746 10571 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Doug Schmidt This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VOHSet_h #pragma once #define _VOHSet_h 1 #include ".Set.h" class VOHSet : public Set { * tab; char* status; int size; int cnt; // keeps track of VALIDCELLs and DELETEDCELLs public: VOHSet(int sz = DEFAULT_INITIAL_CAPACITY); VOHSet(VOHSet&); ~VOHSet(); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); Pix seek( item); void operator |= (VOHSet& b); void operator -= (VOHSet& b); void operator &= (VOHSet& b); int operator == (VOHSet& b); int operator != (VOHSet& b); int operator <= (VOHSet& b); int capacity(); void resize(int newsize = 0); int OK(); }; inline VOHSet::~VOHSet() { delete [size] tab; delete status; } inline int VOHSet::contains(int key) { return seek(key) != 0; } inline & VOHSet::operator () (Pix p) { if (p == 0) error("null Pix"); return *((*)p); } #endif ator &= (VOHSet& b); int operator == (VOHSet& b); int operator != (VOHSet& b); int operator <= (VOHSet& b); int capacity(); void resize(int newsize = 0); int OK(); }; inline VOlibg++/g++-include/sys/socket.h 644 473 0 712 4677677747 11421 #ifndef socket_h #pragma once #include extern "C" { #define KERNEL #include "//usr/include/sys/socket.h" #undef KERNEL #ifndef socket_h #define socket_h 1 #endif // void* in select, since different systems use int* or fd_set* int select(int, void*, void*, void*, struct timeval*); int connect(int, struct sockaddr*, int); int accept(int, struct sockaddr*, int*); int getsockname(int, struct sockaddr*, int*); } #endif libg++/g++-include/sys/resource.h 644 473 0 513 4677677747 11757 #ifndef resource_h #pragma once #include extern "C" { #define KERNEL #include "//usr/include/sys/resource.h" #undef KERNEL #ifndef resource_h #define resource_h 1 #endif int getrusage(int, struct rusage*); int getrlimit (int resource, struct rlimit *rlp); int setrlimit (int resource, struct rlimit *rlp); } #endif sockaddr*, int); int accept(int, struct sockaddr*, int*); int getsockname(int, struct sockaddr*, int*); } #endif libg++/g++-include/sys/wait.h 644 473 0 447 4677677752 11076 #ifndef wait_h #include #define wait WaitStatus extern "C" { #include "//usr/include/sys/wait.h" #undef wait #ifndef wait_h #define wait_h 1 #endif extern int wait3(WaitStatus*, int options, struct rusage*); extern int wait4(int, WaitStatus*, int, struct rusage*); } #endif ce, struct rlimit *rlp); } #endif sockaddr*, int); int accept(int, struct sockaddr*, int*); int getsockname(int, struct sockaddr*, int*); } #endif libg++/g++-include/sys/file.h 644 473 0 1012 4677677752 11056 #ifndef file_h #pragma once /* Some folks need system types.h for things in file.h */ #include #include extern "C" { #define open c_proto_open #define fcntl c_proto_fcntl #ifdef ultrix #define KERNEL #endif #include "//usr/include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl } #endif ile_h #pragma once /* Some folks need system types.h for things in file.h */ #include #include extern "C" { #define open c_proto_open #define fcntl c_proto_fcntl #ifdef ultrix #define KERNEL #endif #include "//usr/include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/stat.h 644 473 0 374 4677677752 11104 #ifndef stat_h #pragma once extern "C" { #include "//usr/include/sys/stat.h" #ifndef stat_h #define stat_h 1 int stat (char *path, struct stat *buf); int lstat (char *path, struct stat *buf); int fstat (int fd, struct stat *buf); #endif } #endif /include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/times.h 644 473 0 37 4677677761 11226 #pragma once #include xtern "C" { #include "//usr/include/sys/stat.h" #ifndef stat_h #define stat_h 1 int stat (char *path, struct stat *buf); int lstat (char *path, struct stat *buf); int fstat (int fd, struct stat *buf); #endif } #endif /include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/time.h 644 473 0 37 4677677761 11043 #pragma once #include xtern "C" { #include "//usr/include/sys/stat.h" #ifndef stat_h #define stat_h 1 int stat (char *path, struct stat *buf); int lstat (char *path, struct stat *buf); int fstat (int fd, struct stat *buf); #endif } #endif /include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/types.h 644 473 0 352 4677677761 11271 #ifndef types_h #pragma once extern "C" { #define size_t ____size_t #define ptrdiff_t ____ptrdiff_t #define wchar_t ____wchar_t #include "//usr/include/sys/types.h" #undef size_t #ifndef types_h #define types_h 1 #endif } #endif #endif } #endif /include/sys/file.h" /* try to guess whether file.h actually gave the right defs */ #if !defined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/param.h 644 473 0 530 4677677762 11224 #ifndef param_h #pragma once #include extern "C" { #define KERNEL #include "//usr/include/sys/param.h" #undef KERNEL #ifndef param_h #define param_h 1 #endif /* kill commonly overloaded possible param.h macros */ #undef setbit #undef clrbit #undef isset #undef isclr #undef howmany #undef roundup #undef MIN #undef MAX } #endif fined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/sys/fcntl.h 644 473 0 303 4677677762 11230 #ifndef sys_fcntl_h #pragma once extern "C" { #define KERNEL #include "//usr/include/sys/fcntl.h" #ifndef sys_fcntl_h #define sys_fcntl_h 1 #endif #undef KERNEL } #include #endif aded possible param.h macros */ #undef setbit #undef clrbit #undef isset #undef isclr #undef howmany #undef roundup #undef MIN #undef MAX } #endif fined(O_RDONLY) || !defined(O_CREAT) || !defined(O_EXCL) #include #endif #ifndef file_h #define file_h 1 #endif #undef KERNEL #undef open #undef fcntl libg++/g++-include/VQueue.ccP 644 473 0 4163 4677677762 11024 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".VQueue.h" VQueue::VQueue(VQueue& b) :size(b.size), cnt(b.cnt), inp(b.inp), outp(b.outp), s(new [b.size]) { int j = outp; for (int i = 0; i < cnt; ++i) { s[j] = b.s[j]; if (++j == size) j = 0; } } void VQueue::operator = (VQueue& b) { if (&b == this) return; if (size != b.size) { delete [size] s; s = new [b.size]; size = b.size; } inp = b.inp; outp = b.outp; cnt = b.cnt; int j = outp; for (int i = 0; i < cnt; ++i) { s[j] = b.s[j]; if (++j == size) j = 0; } } void VQueue::resize(int newsz) { if (newsz < cnt) error("resize: new size too small"); * news = new [newsz]; int j = outp; for (int i = 0; i < cnt; ++i) { news[i] = s[j]; if (++j == size) j = 0; } inp = j; outp = 0; delete [size] s; s = news; size = newsz; } int VQueue::OK() { int v = s != 0; // have space v &= size >= 0; // a legal size v &= inp >= 0 && inp <= size; // pointers with bounds v &= outp >= 0 && outp <= size; int c = (size + inp - outp) % size; v &= cnt == size || cnt == c; // correct count if (!v) error("invariant failure"); return v; } tp; for (int i = 0; i < cnt; ++i) { news[i] = s[j]; if (++j == size) j = 0; } inp = j; outp = 0; delete [size] s; s = news; size = newsz; } int VQueue::OK() { int v = s != 0; // have space v &= size >= 0; // a legal size v &= inp >= 0 && inp <= size; // pointers with bounds v &= outp >= 0 && outp <= size; int c = (size + inp - libg++/g++-include/VQueue.hP 644 473 0 5366 4677677762 10674 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VQueue_h #pragma once #define _VQueue_h 1 #include ".Queue.h" class VQueue : public Queue { protected: int size; int cnt; int inp; int outp; * s; public: VQueue(int sz = DEFAULT_INITIAL_CAPACITY); VQueue(VQueue&); ~VQueue(); void operator = (VQueue&); void enq( item); deq(); & front(); void del_front(); int length(); int empty(); int full(); int capacity(); void resize(int sz); void clear(); int OK(); }; inline VQueue::VQueue(int sz = DEFAULT_INITIAL_CAPACITY) { s = new [size = sz]; cnt = inp = outp = 0; } inline VQueue::~VQueue() { delete [size] s; } inline void VQueue::clear() { inp = outp = 0; cnt = 0; } inline int VQueue::empty() { return cnt <= 0; } inline int VQueue::capacity() { return size; } inline int VQueue::full() { return cnt >= size; } inline int VQueue::length() { return cnt; } inline void VQueue::enq( item) { if (cnt >= size) error("enq to full Queue."); ++cnt; s[inp] = item; if (++inp == size) inp = 0; } inline VQueue::deq() { if (cnt <= 0) error("deq from empty Queue."); --cnt; int i = outp; if (++outp == size) outp = 0; return s[i]; } inline void VQueue::del_front() { if (cnt <= 0) error("delete from empty Queue."); --cnt; if (++outp == size) outp = 0; } inline & VQueue::front() { if (empty()) error("top from empty Queue."); return s[outp]; } #endif > item) { if (cnt >= size) error("enq to full Queue."); ++cnt; s[inp] = item; if (++inp == size) inp = 0; } inline VQueue::deq() { if (cnt <= 0) error("deq from empty Queue."); --cnt; int i = outp; if (++outp == size) outp = 0; return s[i];libg++/g++-include/VStack.ccP 644 473 0 3437 4677677762 11010 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include ".VStack.h" // error handling VStack::VStack(VStack& b) :size(b.size), ptr(b.ptr), s(new [b.size]) { for (int i = 0; i < ptr; ++i) s[i] = b.s[i]; } void VStack::operator = (VStack& b) { if (&b == this) return; if (size < b.ptr) { delete [size] s; s = new [b.size]; size = b.size; } ptr = b.ptr; for (int i = 0; i < ptr; ++i) s[i] = b.s[i]; } void VStack::resize(int newsz) { if (newsz < ptr) error("resize: new size too small"); * news = new [newsz]; for (int i = 0; i < ptr; ++i) news[i] = s[i]; delete [size] s; s = news; size = newsz; } int VStack::OK() { int v = s != 0; // have space v &= size >= 0; // a legal size v &= ptr <= size; // ptr within bounds v &= ptr >= 0; if (!v) error("invariant failure"); return v; } ; for (int i = 0; i < ptr; ++i) s[i] = b.s[i]; } void VStack::resize(int newsz) { if (newsz < ptr) error("resize: new size too small"); * news = new [newsz]; for (int i = 0; i < ptr; ++i) news[i] = s[i]; libg++/g++-include/VStack.hP 644 473 0 5026 4677677763 10647 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _VStack_h #pragma once #define _VStack_h 1 #include ".Stack.h" class VStack : public Stack { protected: int size; int ptr; * s; public: VStack(int sz = DEFAULT_INITIAL_CAPACITY); VStack(VStack&); ~VStack(); void operator = (VStack&); void push( item); pop(); & top(); void del_top(); int length(); int empty(); int full(); void clear(); void resize(int sz); int capacity(); int OK(); }; inline VStack::VStack(int sz = DEFAULT_INITIAL_CAPACITY) { s = new [size = sz]; ptr = 0; } inline VStack::~VStack() { delete [size] s; } inline void VStack::clear() { ptr = 0; } inline int VStack::capacity() { return size; } inline int VStack::empty() { return ptr == 0; } inline int VStack::full() { return ptr == size; } inline int VStack::length() { return ptr; } inline void VStack::push( item) { if (full()) error("push to full stack."); s[ptr++] = item; } inline VStack::pop() { if (empty()) error("pop from empty stack."); return s[--ptr]; } inline void VStack::del_top() { if (empty()) error("del_top from empty stack."); --ptr; } inline & VStack::top() { if (empty()) error("top from empty stack."); return s[ptr-1]; } #endif int VStack::full() { return ptr == size; } inline int VStack::length() { return ptr; } inline void VStack::push( item) { if (full()) error("push to full stack."); s[ptr++] = item; } inline VStack::pop() { if (empty()) error("pop from empty stack."); return s[--ptr]; } inline void VStack::del_top() { if (empty()) error("del_top from empty stack."); --ptr; } inline & VStack::top() { if (empty()) error("top from empty stack."); returlibg++/g++-include/Fix24.h 644 473 0 27120 4677677763 10247 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Fix24_h #pragma once #define _Fix24_h 1 #include #include // extra type definitions typedef struct { long u; unsigned long l; } twolongs; // constant definitions extern const double Fix24_fs, Fix24_mult, Fix24_div, Fix24_max, Fix24_min; extern const unsigned long Fix24_msb, Fix24_lsb, Fix24_m_max, Fix24_m_min; extern const double Fix48_fs, Fix48_max, Fix48_min, Fix48_div_u, Fix48_div_l; extern const twolongs Fix48_msb, Fix48_lsb, Fix48_m_max, Fix48_m_min; // // Fix24 class: 24-bit Fixed point data type // // consists of a 24-bit mantissa (sign bit & 23 data bits). // class Fix24 { friend class Fix48; long m; long assign(double d); operator double(); Fix24(long i); Fix24(int i); public: Fix24(); Fix24(Fix24& f); Fix24(double d); Fix24(Fix48& f); ~Fix24(); Fix24& operator=(Fix24& f); Fix24& operator=(double d); Fix24& operator=(Fix48& f); friend long& mantissa(Fix24& f); friend double value(Fix24& f); Fix24 operator + (); Fix24 operator - (); friend Fix24 operator + (Fix24& f, Fix24& g); friend Fix24 operator - (Fix24& f, Fix24& g); friend Fix48 operator * (Fix24& f, Fix24& g); friend Fix24 operator * (Fix24& f, int g); friend Fix24 operator * (int g, Fix24& f); friend Fix24 operator / (Fix24& f, Fix24& g); friend Fix24 operator << (Fix24& f, int b); friend Fix24 operator >> (Fix24& f, int b); Fix24& operator += (Fix24& f); Fix24& operator -= (Fix24& f); Fix24& operator *= (Fix24& f); Fix24& operator *= (int b); Fix24& operator /= (Fix24& f); Fix24& operator <<=(int b); Fix24& operator >>=(int b); friend int operator == (Fix24& f, Fix24& g); friend int operator != (Fix24& f, Fix24& g); friend int operator >= (Fix24& f, Fix24& g); friend int operator <= (Fix24& f, Fix24& g); friend int operator > (Fix24& f, Fix24& g); friend int operator < (Fix24& f, Fix24& g); friend istream& operator >> (istream& s, Fix24& f); friend ostream& operator << (ostream& s, Fix24& f); void overflow(long&); void range_error(long&); }; // // Fix48 class: 48-bit Fixed point data type // // consists of a 48-bit mantissa (sign bit & 47 data bits). // class Fix48 { friend class Fix24; twolongs m; twolongs assign(double d); operator double(); Fix48(twolongs i); public: Fix48(); Fix48(Fix48& f); Fix48(Fix24& f); Fix48(double d); ~Fix48(); Fix48& operator = (Fix48& f); Fix48& operator = (Fix24& f); Fix48& operator = (double d); friend twolongs& mantissa(Fix48& f); friend double value(Fix48& f); Fix48 operator + (); Fix48 operator - (); friend Fix48 operator + (Fix48& f, Fix48& g); friend Fix48 operator - (Fix48& f, Fix48& g); friend Fix48 operator * (Fix48& f, int g); friend Fix48 operator * (int g, Fix48& f); friend Fix48 operator << (Fix48& f, int b); friend Fix48 operator >> (Fix48& f, int b); friend Fix48 operator * (Fix24& f, Fix24& g); Fix48& operator += (Fix48& f); Fix48& operator -= (Fix48& f); Fix48& operator *= (int b); Fix48& operator <<=(int b); Fix48& operator >>=(int b); friend int operator == (Fix48& f, Fix48& g); friend int operator != (Fix48& f, Fix48& g); friend int operator >= (Fix48& f, Fix48& g); friend int operator <= (Fix48& f, Fix48& g); friend int operator > (Fix48& f, Fix48& g); friend int operator < (Fix48& f, Fix48& g); friend istream& operator >> (istream& s, Fix48& f); friend ostream& operator << (ostream& s, Fix48& f); void overflow(twolongs& i); void range_error(twolongs& i); }; inline Fix24::~Fix24() {} inline Fix24::Fix24(long i) { m = i; } inline Fix24::Fix24(int i) { m = i; } inline Fix24::operator double() { return Fix24_div * m; } inline Fix24::Fix24() { m = 0; } inline Fix24::Fix24(Fix24& f) { m = f.m; } inline Fix24::Fix24(double d) { m = assign(d); } inline Fix24::Fix24(Fix48& f) { m = f.m.u; } inline Fix24& Fix24::operator=(Fix24& f) { m = f.m; return *this; } inline Fix24& Fix24::operator=(double d) { m = assign(d); return *this; } inline Fix24& Fix24::operator=(Fix48& f) { m = f.m.u; return *this; } inline long& mantissa(Fix24& f) { return f.m; } inline double value(Fix24& f) { return double(f); } inline Fix24 Fix24::operator+() { return m; } inline Fix24 Fix24::operator-() { return -m; } inline Fix24 operator+(Fix24& f, Fix24& g) { long sum = f.m + g.m; if ( (f.m ^ sum) & (g.m ^ sum) & Fix24_msb ) f.overflow(sum); return sum; } inline Fix24 operator-(Fix24& f, Fix24& g) { long sum = f.m - g.m; if ( (f.m ^ sum) & (-g.m ^ sum) & Fix24_msb ) f.overflow(sum); return sum; } inline Fix24 operator*(Fix24& a, int b) { return a.m * b; } inline Fix24 operator*(int b, Fix24& a) { return a * b; } inline Fix24 operator<<(Fix24& a, int b) { return a.m << b; } inline Fix24 operator>>(Fix24& a, int b) { return (a.m >> b) & 0xffffff00L; } inline Fix24& Fix24:: operator+=(Fix24& f) { return *this = *this + f; } inline Fix24& Fix24:: operator-=(Fix24& f) { return *this = *this - f; } inline Fix24& Fix24::operator*=(Fix24& f) { return *this = *this * f; } inline Fix24& Fix24:: operator/=(Fix24& f) { return *this = *this / f; } inline Fix24& Fix24:: operator<<=(int b) { return *this = *this << b; } inline Fix24& Fix24:: operator>>=(int b) { return *this = *this >> b; } inline Fix24& Fix24::operator*=(int b) { return *this = *this * b; } inline int operator==(Fix24& f, Fix24& g) { return f.m == g.m; } inline int operator!=(Fix24& f, Fix24& g) { return f.m != g.m; } inline int operator>=(Fix24& f, Fix24& g) { return f.m >= g.m; } inline int operator<=(Fix24& f, Fix24& g) { return f.m <= g.m; } inline int operator>(Fix24& f, Fix24& g) { return f.m > g.m; } inline int operator<(Fix24& f, Fix24& g) { return f.m < g.m; } inline istream& operator>>(istream& s, Fix24& f) { double d; s >> d; f = d; return s; } inline ostream& operator<<(ostream& s, Fix24& f) { return s << double(f); } inline Fix48::~Fix48() {} inline Fix48::Fix48(twolongs i) { m = i; } inline Fix48:: operator double() { /* * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because * m.u is signed and m.l is unsigned. */ return (m.u >= 0)? Fix48_div_u * m.u + Fix48_div_l * m.l : (Fix48_div_u * ((unsigned long)(m.u & 0xffffff00)) + Fix48_div_l * m.l) - 2; } inline Fix48::Fix48() { m.u = 0; m.l = 0; } inline Fix48::Fix48(Fix48& f) { m = f.m; } inline Fix48::Fix48(Fix24& f) { m.u = f.m; m.l = 0; } inline Fix48::Fix48(double d) { m = assign(d); } inline Fix48& Fix48::operator=(Fix48& f) { m = f.m; return *this; } inline Fix48& Fix48::operator=(Fix24& f) { m.u = f.m; m.l = 0; return *this; } inline Fix48& Fix48::operator=(double d) { m = assign(d); return *this; } inline twolongs& mantissa(Fix48& f) { return f.m; } inline double value(Fix48& f) { return double(f); } inline Fix48 Fix48::operator+() { return m; } inline Fix48 Fix48::operator-() { twolongs n; n.l = -m.l; n.u = ~m.u + ((n.l ^ m.l) & Fix24_msb ? 0 : Fix24_lsb); return Fix48(n); } inline Fix48 operator*(int b, Fix48& a) { return a * b; } inline Fix48& Fix48::operator+=(Fix48& f) { return *this = *this + f; } inline Fix48& Fix48::operator-=(Fix48& f) { return *this = *this - f; } inline Fix48& Fix48::operator*=(int b) { return *this = *this * b; } inline Fix48& Fix48::operator<<=(int b) { return *this = *this << b; } inline Fix48& Fix48::operator>>=(int b) { return *this = *this >> b; } inline int operator==(Fix48& f, Fix48& g) { return f.m.u == g.m.u && f.m.l == g.m.l; } inline int operator!=(Fix48& f, Fix48& g) { return f.m.u != g.m.u || f.m.l != g.m.l; } inline int operator>=(Fix48& f, Fix48& g) { return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l); } inline int operator<=(Fix48& f, Fix48& g) { return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l); } inline int operator>(Fix48& f, Fix48& g) { return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l); } inline int operator<(Fix48& f, Fix48& g) { return f.m.u < g.m.u || (f.m.u == g.m.u && f.m.l < g.m.l); } inline istream& operator>>(istream& s, Fix48& f) { double d; s >> d; f = d; return s; } inline ostream& operator<<(ostream& s, Fix48& f) { return s << double(f); } // active error handler declarations typedef void (*Fix24_peh)(long&); typedef void (*Fix48_peh)(twolongs&); extern Fix24_peh Fix24_overflow_handler; extern Fix48_peh Fix48_overflow_handler; extern Fix24_peh Fix24_range_error_handler; extern Fix48_peh Fix48_range_error_handler; // error handler declarations extern Fix24_peh set_Fix24_overflow_handler(Fix24_peh); extern Fix48_peh set_Fix48_overflow_handler(Fix48_peh); extern void set_overflow_handler(Fix24_peh, Fix48_peh); extern Fix24_peh set_Fix24_range_error_handler(Fix24_peh); extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh); extern void set_range_error_handler(Fix24_peh, Fix48_peh); extern void Fix24_ignore(long&), Fix24_overflow_saturate(long&), Fix24_overflow_warning_saturate(long&), Fix24_warning(long&), Fix24_abort(long&); extern void Fix48_ignore(twolongs&), Fix48_overflow_saturate(twolongs&), Fix48_overflow_warning_saturate(twolongs&), Fix48_warning(twolongs&), Fix48_abort(twolongs&); #endif 4_peh set_Fix24_range_error_handler(Fix24_peh); extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh); extern void set_range_error_handler(Fix24_peh, Fix48_peh); extern void Fix24_ignore(long&), Fix24_overflow_saturate(long&), Fix24_overflow_warning_saturate(long&), Fix24_warning(long&), Fix24_abort(long&); extern void Fix48_ignore(twolongs&), Fix48_overflow_saturate(twolongs&), Fix48_overflow_warning_saturlibg++/g++-include/Vec.hP 644 473 0 7744 4677677763 10202 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Vec_h #pragma once #define _Vec_h 1 #ifndef __typedefs #define __typedefs 1 typedef void (*Procedure)(); typedef (*Mapper)(); typedef (*Combiner)(, ); typedef int (*Predicate)(); typedef int (*Comparator)(, ); #endif class Vec { protected: int len; *s; Vec(int l, * d); public: Vec (); Vec (int l); Vec (int l, fill_value); Vec (Vec&); ~Vec (); Vec & operator = (Vec & a); Vec at(int from = 0, int n = -1); int capacity(); void resize(int newlen); & operator [] (int n); & elem(int n); friend Vec concat(Vec & a, Vec & b); friend Vec map(Mapper f, Vec & a); friend Vec merge(Vec & a, Vec & b, Comparator f); friend Vec combine(Combiner f, Vec & a, Vec & b); friend Vec reverse(Vec & a); void reverse(); void sort(Comparator f); void fill( val, int from = 0, int n = -1); void apply(Procedure f); reduce(Combiner f, base); int index( targ); friend int operator == (Vec& a, Vec& b); friend int operator != (Vec& a, Vec& b); void error(const char* msg); void range_error(); }; inline Vec::Vec() { len = 0; s = 0; } inline Vec::Vec(int l) { s = new [len = l]; } inline Vec::Vec(int l, fill_value) { s = new [len = l]; * top = &(s[len]); * t = s; while (t < top) *t++ = fill_value; } inline Vec::Vec(int l, * d) { len = l; s = d; } inline Vec::Vec(Vec& v) { s = new [len = v.len]; * top = &(s[len]); * t = s; * u = v.s; while (t < top) *t++ = *u++; } inline Vec::~Vec() { delete[len] s; } inline Vec& Vec::operator = (Vec& v) { if (this != &v) { delete[len] s; s = new [len = v.len]; * top = &(s[len]); * t = s; * u = v.s; while (t < top) *t++ = *u++; } return *this; } inline & Vec::operator [] (int n) { if ((unsigned)n >= len) range_error(); return s[n]; } inline & Vec::elem(int n) { return s[n]; } inline int Vec::capacity() { return len; } inline void Vec::apply(Procedure f) { * top = &(s[len]); * t = s; while (t < top) (*f)(*t++); } inline int operator != (Vec& a, Vec& b) { return !(a == b); } extern void default_Vec_error_handler(const char*); extern one_arg_error_handler_t Vec_error_handler; extern one_arg_error_handler_t set_Vec_error_handler(one_arg_error_handler_t f); #endif rn s[n]; } inline & Vlibg++/g++-include/XPBag.ccP 644 473 0 3373 4677677763 10556 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".XPBag.h" int XPBag::OK() { int v = p.OK(); v &= count == p.length(); if (!v) error("invariant failure"); return v; } Pix XPBag::seek( item, Pix i = 0) { if (i == 0) i = p.first(); else next(i); for (; i != 0; p.next(i)) if (EQ(p(i), item)) return i; return 0; } int XPBag::nof( item) { int n = 0; for (int i = p.low(); i < p.fence(); p.next(i)) if (EQ(p[i], item)) ++n; return n; } void XPBag::del( item) { for (int i = p.low(); i < p.fence(); p.next(i)) { if (EQ(p[i], item)) { --count; p[i] = p.low_element(); p.del_low(); return; } } } void XPBag::remove( item) { for (int i = p.low(); i < p.fence(); p.next(i)) { if (EQ(p[i], item)) { --count; p[i] = p.low_element(); p.del_low(); } } } nt n = 0; for (int i = p.low(); i < p.fence(); p.next(i)) if (EQ(p[i], item)) ++n; return n; } void XPBag::del( item) { for (int i = p.low(); i < p.fence(); p.next(i)) { if (EQ(p[i], item)) { --count; p[i] = p.low_elemelibg++/g++-include/XPBag.hP 644 473 0 4347 4677677763 10422 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPBag_h #pragma once #define _XPBag_h 1 #include ".Bag.h" #include ".XPlex.h" class XPBag : public Bag { protected: XPlex p; public: XPBag(int chunksize = DEFAULT_INITIAL_CAPACITY); XPBag(const XPBag&); Pix add( item); void del( item); void remove(item); int nof( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item, Pix from = 0); int OK(); }; inline XPBag::XPBag(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) { count = 0; } inline XPBag::XPBag(const XPBag& s) : p(s.p) { count = s.count; } inline Pix XPBag::first() { return p.first(); } inline void XPBag::next(Pix & idx) { p.next(idx); } inline & XPBag::operator ()(Pix idx) { return p(idx); } inline void XPBag::clear() { count = 0; p.clear(); } inline int XPBag::owns (Pix idx) { return p.owns(idx); } inline Pix XPBag::add( item) { ++count; return p.index_to_Pix(p.add_high(item)); } inline int XPBag::contains( item) { return seek(item) != 0; } #endif ) : p(s.p) { count = s.count; } inline Pix XPBag::first() { return p.first(); } inline void XPBag::next(Pix & idx) { p.next(idx); } inline & XPBag::operator ()(Pix idx) { return p(idx); } inline void XPBag::clear() { count = 0; p.clear(); } inline ilibg++/g++-include/XPDeque.hP 644 473 0 5314 4677677763 10767 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPDeque_h #pragma once #define _XPDeque_h #include ".XPlex.h" #include ".Deque.h" class XPDeque : public Deque { XPlex p; public: XPDeque(int chunksize = DEFAULT_INITIAL_CAPACITY); XPDeque(const XPDeque& d); ~XPDeque(); void operator = (const XPDeque&); void push( item); // insert at front void enq( item); // insert at rear & front(); & rear(); deq(); void del_front(); void del_rear(); void clear(); int empty(); int full(); int length(); int OK(); }; inline XPDeque::XPDeque(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) {} inline XPDeque::XPDeque(const XPDeque& d) : p(d.p) {} inline XPDeque::~XPDeque() {} inline void XPDeque::push(item) { p.add_low(item); } inline void XPDeque::enq(item) { p.add_high(item); } inline XPDeque::deq() { res = p.low_element(); p.del_low(); return res; } inline & XPDeque::front() { return p.low_element(); } inline & XPDeque::rear() { return p.high_element(); } inline void XPDeque::del_front() { p.del_low(); } inline void XPDeque::del_rear() { p.del_high(); } inline void XPDeque::operator =(const XPDeque& s) { p.operator = (s.p); } inline int XPDeque::empty() { return p.empty(); } inline int XPDeque::full() { return p.full(); } inline int XPDeque::length() { return p.length(); } inline int XPDeque::OK() { return p.OK(); } inline void XPDeque::clear() { p.clear(); } #endif ::rear() { return p.high_element(); } inline void XPDeque::del_front() { p.del_low(); } inline void XPDeque::del_rear() { p.del_high(); } inline void XPDeque::operator =(const XPDeque& s) { p.operator = (s.p); } inline int XPDeque::empty() { return p.empty(); } inline int Xlibg++/g++-include/XPPQ.ccP 644 473 0 5635 4677677764 10411 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".XPPQ.h" int XPPQ::OK() { int v = p.OK(); v &= p.low() == 1; v &= count == p.length(); if (!v) error("invariant failure"); return v; } Pix XPPQ::seek( item) { for (int i = p.low(); i < p.fence(); p.next(i)) if (EQ(p[i],item)) return p.index_to_Pix(i); return 0; } // standard 2-ary heap ops // pointers are used a lot to avoid thrashing across chunks with plexes Pix XPPQ::enq( item) { p.add_high(item); * pk = &(p.high_element()); int par = ++count >> 1; while (par != 0) { * ppar = &(p[par]); if (!(LE(*ppar, item))) { *pk = *ppar; pk = ppar; par >>= 1; } else break; } *pk = item; return Pix(pk); } void XPPQ::del_front() { if (count == 0) error("empty PQ"); --count; * pk = &(p.low_element()); * ph = &(p.high_element()); int child = 2; while (child <= count) { * pchild = &(p[child]); if (child < count) { * prchild = &(p[child+1]); if (!(LE(*pchild, *prchild))) { pchild = prchild; ++child; } } if (!(LE(*ph, *pchild))) { *pk = *pchild; pk = pchild; child <<= 1; } else break; } *pk = *ph; p.del_high(); } void XPPQ::del(Pix i) { if (i == 0) error("null Pix"); --count; int k = p.Pix_to_index(i); * pk = &(p[k]); * ph = &(p.high_element()); int child = k << 1; while (child <= count) { * pchild = &(p[child]); if (child < count) { * prchild = &(p[child+1]); if (!(LE(*pchild, *prchild))) { pchild = prchild; ++child; } } if (!(LE(*ph, *pchild))) { *pk = *pchild; pk = pchild; child <<= 1; } else break; } int par = child >> 2; while (par != 0) { * ppar = &(p[par]); if (!(LE(*ppar, *ph))) { *pk = *ppar; pk = ppar; par >>= 1; } else break; } *pk = *ph; p.del_high(); } < count) { * prchild = &(p[child+1]); if (!(LE(*pchild, *prchild))) { libg++/g++-include/XPPQ.hP 644 473 0 4457 4677677764 10254 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPPQ_h #pragma once #define _XPPQ_h 1 #include ".PQ.h" #include ".XPlex.h" class XPPQ : public PQ { protected: XPlex p; public: XPPQ(int chunksize = DEFAULT_INITIAL_CAPACITY); XPPQ(const XPPQ&); Pix enq( item); deq(); & front(); void del_front(); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); void del(Pix i); int owns(Pix i); Pix seek( item); int OK(); // rep invariant }; inline XPPQ::XPPQ(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(1, chunksize) { count = 0; } inline XPPQ::XPPQ(const XPPQ& s) : p(s.p) { count = s.count; } inline Pix XPPQ::first() { return p.first(); } inline void XPPQ::next(Pix & idx) { p.next(idx); } inline & XPPQ::operator ()(Pix idx) { return p(idx); } inline & XPPQ::front () { return p.low_element(); } inline XPPQ::deq () { x = p.low_element(); del_front(); return x; } inline void XPPQ::clear() { count = 0; p.clear(); } inline int XPPQ::contains ( item) { return seek(item) != 0; } inline int XPPQ::owns (Pix idx) { return p.owns(idx); } #endif PPQ::first() { return p.first(); } inline void XPPQ::next(Pix & idx) { p.next(idx); } inline & XPPQ::operator ()(Pix idx) { return p(idx); } inline & XPPQ::front () { return p.low_libg++/g++-include/XPQueue.hP 644 473 0 4624 4677677764 11014 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPQueue_h #pragma once #define _XPQueue_h #include ".XPlex.h" #include ".Queue.h" class XPQueue : public Queue { protected: XPlex p; public: XPQueue(int chunksize = DEFAULT_INITIAL_CAPACITY); XPQueue(const XPQueue& q); ~XPQueue(); void operator = (const XPQueue&); void enq( item); deq(); & front(); void del_front(); void clear(); int empty(); int full(); int length(); int OK(); }; inline XPQueue::XPQueue(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) {} inline XPQueue::XPQueue(const XPQueue& q) : p(q.p) {} inline XPQueue::~XPQueue() {} inline void XPQueue::enq(item) { p.add_high(item); } inline XPQueue::deq() { res = p.low_element(); p.del_low(); return res; } inline & XPQueue::front() { return p.low_element(); } inline void XPQueue::del_front() { p.del_low(); } inline void XPQueue::operator =(const XPQueue& s) { p.operator = (s.p); } inline int XPQueue::empty() { return p.empty(); } inline int XPQueue::full() { return p.full(); } inline int XPQueue::length() { return p.length(); } inline int XPQueue::OK() { return p.OK(); } inline void XPQueue::clear() { p.clear(); } #endif ; p.del_low(); return res; } inline & XPQueue::front() { return p.low_element(); } inline voilibg++/g++-include/XPSet.ccP 644 473 0 3057 4677677764 10620 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".XPSet.h" int XPSet::OK() { int v = p.OK(); v &= count == p.length(); if (!v) error("invariant failure"); return v; } Pix XPSet::seek( item) { for (int i = p.low(); i < p.fence(); p.next(i)) if (EQ(p[i],item)) return p.index_to_Pix(i); return 0; } Pix XPSet::add( item) { Pix i = seek(item); if (i == 0) { ++count; i = p.index_to_Pix(p.add_high(item)); } return i; } void XPSet::del( item) { for (int i = p.low(); i < p.fence(); p.next(i)) { if (EQ(p[i], item)) { --count; p[i] = p.low_element(); p.del_low(); return; } } } n v; } Pix XPSet::seek( item) { for (int i = p.low(); i < p.fence(); p.next(i)) if (EQ(p[i],item)) return p.index_to_Pix(i); return 0; } Pix XPSet::add( item) { Pix i = seek(item); if (i == 0) { ++count; i = p.index_to_Pix(p.add_high(item)); } return i; } void XPSet::del( item) { for (int i = p.low(); i < p.fence(); p.next(i)) { if (EQ(p[i], item)) { --count; p[i] = p.low_element();libg++/g++-include/XPSet.hP 644 473 0 4072 4677677764 10460 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPSet_h #pragma once #define _XPSet_h 1 #include ".Set.h" #include ".XPlex.h" class XPSet : public Set { protected: XPlex p; public: XPSet(int chunksize = DEFAULT_INITIAL_CAPACITY); XPSet(const XPSet&); Pix add( item); void del( item); int contains( item); void clear(); Pix first(); void next(Pix& i); & operator () (Pix i); int owns(Pix i); Pix seek( item); int OK(); }; inline XPSet::XPSet(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) { count = 0; } inline XPSet::XPSet(const XPSet& s) : p(s.p) { count = s.count; } inline Pix XPSet::first() { return p.first(); } inline void XPSet::next(Pix & idx) { p.next(idx); } inline & XPSet::operator ()(Pix idx) { return p(idx); } inline void XPSet::clear() { count = 0; p.clear(); } inline int XPSet::contains ( item) { return seek(item) != 0; } inline int XPSet::owns (Pix idx) { return p.owns(idx); } #endif AL_CAPACITY) : p(chunksize) { count = 0; } inline XPSet::XPSet(const XPSet& s) : p(s.p) { count = s.count; } inline Pix XPSet::first() { return p.first(); } inline void XPSet::next(Pix & idx) { p.next(idx); } inline & XPSet::operator ()(Pix idx) { return p(idx); } inline void XPSet::clear() { count = 0; p.clear(); } inline int XPSet::contains ( item) { return seek(item) != 0; } inline int Xlibg++/g++-include/XPStack.hP 644 473 0 4622 4677677764 10773 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPStack_h #pragma once #define _XPStack_h #include ".XPlex.h" #include ".Stack.h" class XPStack : public Stack { XPlex p; public: XPStack(int chunksize = DEFAULT_INITIAL_CAPACITY); XPStack(const XPStack& s); ~XPStack(); void operator = (const XPStack&); void push( item); pop(); & top(); void del_top(); int empty(); int full(); int length(); void clear(); int OK(); }; inline XPStack::XPStack(int chunksize = DEFAULT_INITIAL_CAPACITY) : p(chunksize) {} inline XPStack::XPStack(const XPStack& s) : p(s.p) {} inline XPStack::~XPStack() {} inline void XPStack::push(item) { p.add_high(item); } inline XPStack::pop() { res = p.high_element(); p.del_high(); return res; } inline & XPStack::top() { return p.high_element(); } inline void XPStack::del_top() { p.del_high(); } inline void XPStack::operator =(const XPStack& s) { p.operator = (s.p); } inline int XPStack::empty() { return p.empty(); } inline int XPStack::full() { return p.full(); } inline int XPStack::length() { return p.length(); } inline int XPStack::OK() { return p.OK(); } inline void XPStack::clear() { p.clear(); } #endif p.del_high(); return res; } inline & XPStack::top() { return p.high_element(); } inline void XPlibg++/g++-include/XPlex.ccP 644 473 0 20256 4677677765 10676 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include ".XPlex.h" XPlex:: XPlex() { lo = fnc = 0; csize = DEFAULT_INITIAL_CAPACITY; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, lo+csize)); hd = ch; } XPlex:: XPlex(int chunksize) { if (chunksize == 0) error("invalid constructor specification"); lo = fnc = 0; if (chunksize > 0) { csize = chunksize; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, csize)); hd = ch; } else { csize = -chunksize; * data = new [csize]; set_cache(new IChunk(data, chunksize, lo, fnc, fnc)); hd = ch; } } XPlex:: XPlex(int l, int chunksize) { if (chunksize == 0) error("invalid constructor specification"); lo = fnc = l; if (chunksize > 0) { csize = chunksize; * data = new [csize]; set_cache(new IChunk(data, lo, lo, fnc, csize+lo)); hd = ch; } else { csize = -chunksize; * data = new [csize]; set_cache(new IChunk(data, chunksize+lo, lo, fnc, fnc)); hd = ch; } } void XPlex::make_initial_chunks(int up = 1) { int need = fnc - lo; hd = 0; if (up) { int l = lo; do { int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; IChunk* h = new IChunk(data, l, l, l+sz, l+csize); if (hd != 0) h->link_to_next(hd); else hd = h; l += sz; need -= sz; } while (need > 0); } else { int hi = fnc; do { int sz; if (need >= csize) sz = csize; else sz = need; * data = new [csize]; IChunk* h = new IChunk(data, hi-csize, hi-sz, hi, hi); if (hd != 0) h->link_to_next(hd); hd = h; hi -= sz; need -= sz; } while (need > 0); } set_cache(hd); } XPlex:: XPlex(int l, int hi, const initval, int chunksize = 0) { lo = l; fnc = hi + 1; if (chunksize == 0) { csize = fnc - l; make_initial_chunks(1); } else if (chunksize < 0) { csize = -chunksize; make_initial_chunks(0); } else { csize = chunksize; make_initial_chunks(1); } fill(initval); } XPlex::XPlex(const XPlex& a) { lo = a.lo; fnc = a.fnc; csize = a.csize; make_initial_chunks(); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } void XPlex::operator= (const XPlex& a) { if (&a != this) { invalidate(); lo = a.lo; fnc = a.fnc; csize = a.csize; make_initial_chunks(); for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; } } void XPlex::cache(int idx) const { const IChunk* tail = tl(); const IChunk* t = ch; while (idx >= t->fence_index()) { if (t == tail) index_error(); t = (t->next()); } while (idx < t->low_index()) { if (t == hd) index_error(); t = (t->prev()); } set_cache(t); } void XPlex::cache(const * p) const { const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) index_error(); } set_cache(t); } int XPlex::owns(Pix p) const { const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) { set_cache(t); return 0; } } set_cache(t); return 1; } * XPlex::dosucc(const * p) const { if (p == 0) return 0; const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->next()); if (t == old) return 0; } int i = t->index_of(p) + 1; if (i >= fnc) return 0; if (i >= t->fence_index()) t = (t->next()); set_cache(t); return (t->pointer_to(i)); } * XPlex::dopred(const * p) const { if (p == 0) return 0; const IChunk* old = ch; const IChunk* t = ch; while (!t->actual_pointer(p)) { t = (t->prev()); if (t == old) return 0; } int i = t->index_of(p) - 1; if (i < lo) return 0; if (i < t->low_index()) t = (t->prev()); set_cache(t); return (t->pointer_to(i)); } int XPlex::add_high(const elem) { IChunk* t = tl(); if (!t->can_grow_high()) { if (t->IChunk::empty() && one_chunk()) t->clear(fnc); else { * data = new [csize]; t = (new IChunk(data, fnc, fnc, fnc,fnc+csize)); t->link_to_prev(tl()); } } *((t->IChunk::grow_high())) = elem; set_cache(t); return fnc++; } int XPlex::del_high () { if (empty()) empty_error(); IChunk* t = tl(); t->IChunk::shrink_high(); if (t->IChunk::empty() && !one_chunk()) { IChunk* pred = t->prev(); del_chunk(t); t = pred; } set_cache(t); return --fnc - 1; } int XPlex::add_low (const elem) { IChunk* t = hd; if (!t->can_grow_low()) { if (t->IChunk::empty() && one_chunk()) t->cleardown(lo); else { * data = new [csize]; hd = new IChunk(data, lo-csize, lo, lo, lo); hd->link_to_next(t); t = hd; } } *((t->IChunk::grow_low())) = elem; set_cache(t); return --lo; } int XPlex::del_low () { if (empty()) empty_error(); IChunk* t = hd; t->IChunk::shrink_low(); if (t->IChunk::empty() && !one_chunk()) { hd = t->next(); del_chunk(t); t = hd; } set_cache(t); return ++lo; } void XPlex::append (const XPlex& a) { for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); } void XPlex::prepend (const XPlex& a) { for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); } void XPlex::reverse() { tmp; int l = lo; int h = fnc - 1; IChunk* loch = hd; IChunk* hich = tl(); while (l < h) { * lptr = loch->pointer_to(l); * hptr = hich->pointer_to(h); tmp = *lptr; *lptr = *hptr; *hptr = tmp; if (++l >= loch->fence_index()) loch = loch->next(); if (--h < hich->low_index()) hich = hich->prev(); } } void XPlex::fill(const x) { for (int i = lo; i < fnc; ++i) (*this)[i] = x; } void XPlex::fill(const x, int l, int hi) { for (int i = l; i <= hi; ++i) (*this)[i] = x; } void XPlex::clear() { if (fnc != lo) { IChunk* t = tl(); while (t != hd) { IChunk* prv = t->prev(); del_chunk(t); t = prv; } t->IChunk::clear(lo); set_cache(t); fnc = lo; } } int XPlex::OK () const { int v = hd != 0 && ch != 0; // at least one chunk v &= fnc == tl()->fence_index();// last chunk fence == plex fence v &= lo == ((hd))->IChunk::low_index(); // first lo == plex lo // loop for others: int found_ch = 0; // to make sure ch is in list; const IChunk* t = (hd); for (;;) { if (t == ch) ++found_ch; v &= t->IChunk::OK(); // each chunk is OK if (t == tl()) break; else // and has indices contiguous to succ { v &= t->top_index() == t->next()->base_index(); if (t != hd) // internal chunks full { v &= !t->empty(); v &= !t->can_grow_low(); v &= !t->can_grow_high(); } t = t->next(); } } v &= found_ch == 1; if (!v) error("invariant failure"); return v; } und_ch; v &= t->IChunk::OK(); // each chunk is OK if (t == tl()) break; else // and has indices contiguous to succ { v &= t->top_index() == t->next()->base_index(); if (t != hd) // internal chunks full { v &= !t->empty(); libg++/g++-include/XPlex.hP 644 473 0 13747 4677677765 10547 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) based on code by Marc Shapiro (shapiro@sor.inria.fr) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _XPlex_h #pragma once #define _XPlex_h 1 #include ".Plex.h" class XPlex: public Plex { IChunk* ch; // cached chunk void make_initial_chunks(int up = 1); void cache(int idx) const; void cache(const * p) const; * dopred(const * p) const; * dosucc(const * p) const; void set_cache(const IChunk* t) const; // logically, // not physically const public: XPlex(); // set low = 0; // fence = 0; // csize = default XPlex(int ch_size); // low = 0; // fence = 0; // csize = ch_size XPlex(int lo, // low = lo; int ch_size); // fence=lo // csize = ch_size XPlex(int lo, // low = lo int hi, // fence = hi+1 const initval,// fill with initval, int ch_size = 0); // csize= ch_size // or fence-lo if 0 XPlex(const XPlex&); void operator= (const XPlex&); // virtuals & high_element (); & low_element (); const & high_element () const; const & low_element () const; Pix first() const; Pix last() const; void prev(Pix& ptr) const; void next(Pix& ptr) const; int owns(Pix p) const; & operator () (Pix p); const & operator () (Pix p) const; int low() const; int high() const; int valid(int idx) const; void prev(int& idx) const; void next(int& x) const; & operator [] (int index); const & operator [] (int index) const; int Pix_to_index(Pix p) const; Pix index_to_Pix(int idx) const; int can_add_high() const; int can_add_low() const; int full() const; int add_high(const elem); int del_high (); int add_low (const elem); int del_low (); void fill(const x); void fill(const x, int from, int to); void clear(); void reverse(); void append(const XPlex& a); void prepend(const XPlex& a); int OK () const; }; inline void XPlex::prev(int& idx) const { --idx; } inline void XPlex::next(int& idx) const { ++idx; } inline int XPlex::full () const { return 0; } inline int XPlex::can_add_high() const { return 1; } inline int XPlex::can_add_low() const { return 1; } inline int XPlex::valid (int idx) const { return idx >= lo && idx < fnc; } inline int XPlex::low() const { return lo; } inline int XPlex::high() const { return fnc - 1; } inline & XPlex:: operator [] (int idx) { if (!ch->actual_index(idx)) cache(idx); return *(ch->pointer_to(idx)); } inline const & XPlex:: operator [] (int idx) const { if (!ch->actual_index(idx)) cache(idx); return *((const *)(ch->pointer_to(idx))); } inline & XPlex::low_element () { if (empty()) index_error(); return *(hd->pointer_to(lo)); } inline const & XPlex::low_element () const { if (empty()) index_error(); return *((const *)(hd->pointer_to(lo))); } inline & XPlex::high_element () { if (empty()) index_error(); return *(tl()->pointer_to(fnc - 1)); } inline const & XPlex::high_element () const { if (empty()) index_error(); return *((const *)(tl()->pointer_to(fnc - 1))); } inline int XPlex::Pix_to_index(Pix p) const { if (!ch->actual_pointer(p)) cache(p); return ch->index_of(p); } inline Pix XPlex::index_to_Pix(int idx) const { if (!ch->actual_index(idx)) cache(idx); return (Pix)(ch->pointer_to(idx)); } inline Pix XPlex::first() const { return Pix(hd->IChunk::first_pointer()); } inline Pix XPlex::last() const { return Pix(tl()->IChunk::last_pointer()); } inline void XPlex::prev(Pix& p) const { Pix q = Pix(ch->IChunk::pred((*) p)); p = (q == 0)? Pix(dopred((const *) p)) : q; } inline void XPlex::next(Pix& p) const { Pix q = Pix(ch->IChunk::succ((*) p)); p = (q == 0)? Pix(dosucc((const *)p)) : q; } inline & XPlex:: operator () (Pix p) { return *((*)p); } inline const & XPlex:: operator () (Pix p) const { return *((const *)p); } inline void XPlex::set_cache(const IChunk* t) const { ((XPlex*)(this))->ch = t; } #endif (Pix& p) const { Pix q libg++/g++-include/defs.hP 644 473 0 3002 4677677765 10367 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _defs_h #pragma once #define _defs_h 1 // equality operator #ifndef EQ #define EQ(a, b) ((a) == (b)) #endif // less-than-or-equal #ifndef LE #define LE(a, b) ((a) <= (b)) #endif // comparison : less-than -> < 0; equal -> 0; greater-than -> > 0 #ifndef CMP #define CMP(a, b) ( ((a) <= (b))? (((a) == (b))? 0 : -1) : 1 ) #endif // hash function #ifndef HASH extern unsigned int hash(); #define HASH(x) hash(x) #endif // initial capacity for structures requiring one #ifndef DEFAULT_INITIAL_CAPACITY #define DEFAULT_INITIAL_CAPACITY 100 #endif #endif #define EQ(a, b) ((a) == (b)) #endif // less-than-or-equal #ifndef LE #define LE(a, b) ((a) <= (b)) #endif // comparison : less-than -> < 0; equal -> 0; greater-than -> > 0 #ifndef CMP #define CMP(a, b) ( ((a) <= (b))? (((a) == (b))? 0 : -1) : 1 ) #endif // hash function #ifndef HASH extern unsigned int hash(); #define HASH(x) hash(x) #endif // initial capacity for structures requiring one #ifndef DEFAULT_INITIAL_CAPACITY #define DEFAULT_INITIAL_CAPACITY 100 #endif #endilibg++/g++-include/CursesWindow.h 644 473 0 22236 4677677765 12014 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Eric Newton (newton@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _CursesWindow_h #pragma once #define _CursesWindow_h #pragma once #include /* * * C++ class for windows. * * */ class CursesWindow { protected: static int count; // count of all active windows: // We rely on the c++ promise that // all otherwise uninitialized // static class vars are set to 0 WINDOW * w; // the curses WINDOW int alloced; // true if we own the WINDOW CursesWindow* par; // parent, if subwindow CursesWindow* subwins; // head of subwindows list CursesWindow* sib; // next subwindow of parent void kill_subwindows(); // disable all subwindows public: CursesWindow(WINDOW* &window); // useful only for stdscr CursesWindow(int lines, // number of lines int cols, // number of columns int begin_y, // line origin int begin_x); // col origin CursesWindow(CursesWindow& par, // parent window int lines, // number of lines int cols, // number of columns int by, // absolute or relative int bx, // origins: char absrel = 'a'); // if `a', by & bx are // absolute screen pos, // else if `r', they are // relative to par origin ~CursesWindow(); // terminal status int lines(); // number of lines on terminal, *not* window int cols(); // number of cols on terminal, *not* window // window status int height(); // number of lines in this window int width(); // number of cols in this window int begx(); // smallest x coord in window int begy(); // smallest y coord in window int maxx(); // largest x coord in window int maxy(); // largest x coord in window // window positioning int move(int y, int x); // coordinate positioning void getyx(int& y, int& x); int mvcur(int sy, int ey, int sx, int ex); // input int getch(); int getstr(char * str); int scanw(const char *, ...); // input + positioning int mvgetch(int y, int x); int mvgetstr(int y, int x, char * str); int mvscanw(int, int, const char*, ...); // output int addch(const char ch); int addstr(const char * str); int printw(const char * fmt, ...); int inch(); int insch(char c); int insertln(); // output + positioning int mvaddch(int y, int x, char ch); int mvaddstr(int y, int x, char * str); int mvprintw(int y, int x, const char * fmt, ...); int mvinch(int y, int x); int mvinsch(int y, int x, char ch); // borders int box(char vert, char hor); // erasure int erase(); int clear(); int clearok(cbool bf); int clrtobot(); int clrtoeol(); int delch(); int mvdelch(int y, int x); int deleteln(); // screen control int scroll(); int scrollok(cbool bf); int touchwin(); int touchline(int y, int sx, int ex); int refresh(); int leaveok(cbool bf); int flushok(cbool bf); int standout(); int standend(); // multiple window control int overlay(CursesWindow &win); int overwrite(CursesWindow &win); #ifndef DGUX int touchoverlap(CursesWindow &win); #endif // traversal support CursesWindow* child(); CursesWindow* sibling(); CursesWindow* parent(); }; inline int CursesWindow::begx() { return w->_begx; } inline int CursesWindow::begy() { return w->_begy; } inline int CursesWindow::maxx() { return w->_maxx; } inline int CursesWindow::maxy() { return w->_maxy; } inline int CursesWindow::height() { return maxy() - begy() + 1; } inline int CursesWindow::width() { return maxx() - begx() + 1; } inline int CursesWindow::box(char vert, char hor) { return ::box(w, vert, hor); } inline int CursesWindow::overlay(CursesWindow &win) { return ::overlay(w, win.w); } inline int CursesWindow::overwrite(CursesWindow &win) { return ::overwrite(w, win.w); } inline int CursesWindow::scroll() { return ::scroll(w); } #ifndef DGUX inline int CursesWindow::touchoverlap(CursesWindow &win) { return ::touchoverlap(w, win.w); } #endif inline int CursesWindow::touchwin() { return ::touchwin(w); } inline int CursesWindow::addch(const char ch) { return ::waddch(w, ch); } inline int CursesWindow::addstr(const char * str) { return ::waddstr(w, str); } inline int CursesWindow::clear() { return ::wclear(w); } inline int CursesWindow::clrtobot() { return ::wclrtobot(w); } inline int CursesWindow::clrtoeol() { return ::wclrtoeol(w); } inline int CursesWindow::delch() { return ::wdelch(w); } inline int CursesWindow::deleteln() { return ::wdeleteln(w); } inline int CursesWindow::erase() { return ::werase(w); } inline int CursesWindow::getch() { return ::wgetch(w); } inline int CursesWindow::getstr(char * str) { return ::wgetstr(w, str); } inline int CursesWindow::inch() { return winch(w); } inline int CursesWindow::insch(char c) { return ::winsch(w, c); } inline int CursesWindow::insertln() { return ::winsertln(w); } inline int CursesWindow::move(int y, int x) { return ::wmove(w, y, x); } inline int CursesWindow::touchline(int y, int sx, int ex) { return ::touchline(w, y, sx, ex); } inline int CursesWindow::mvcur(int sy, int ey, int sx, int ex) { return ::mvcur(sy, ey, sx,ex); } inline int CursesWindow::mvaddch(int y, int x, char ch) { return (::wmove(w, y, x)==0) ? 0 : ::waddch(w, ch); } inline int CursesWindow::mvgetch(int y, int x) { return (::wmove(w, y, x)==0) ? 0 : ::wgetch(w); } inline int CursesWindow::mvaddstr(int y, int x, char * str) { return (::wmove(w, y, x)==0) ? 0 : ::waddstr(w, str); } inline int CursesWindow::mvgetstr(int y, int x, char * str) { return (::wmove(w, y, x)==0) ? 0 : ::wgetstr(w, str); } inline int CursesWindow::mvinch(int y, int x) { return (::wmove(w, y, x)==0) ? 0 : ::winch(w); } inline int CursesWindow::mvdelch(int y, int x) { return (::wmove(w, y, x)==0) ? 0 : ::wdelch(w); } inline int CursesWindow::mvinsch(int y, int x, char ch) { return (::wmove(w, y, x)==0) ? 0 : ::winsch(w, ch); } inline int CursesWindow::refresh() { return ::wrefresh(w); } inline int CursesWindow::clearok(cbool bf) { return ::clearok(w,bf); } inline int CursesWindow::leaveok(cbool bf) { return ::leaveok(w,bf); } inline int CursesWindow::scrollok(cbool bf) { return ::scrollok(w,bf); } inline int CursesWindow::flushok(cbool bf) { return ::flushok(w, bf); } inline void CursesWindow::getyx(int& y, int& x) { ::getyx(w, y, x); } inline int CursesWindow::standout() { return ::wstandout(w); } inline int CursesWindow::standend() { return ::wstandend(w); } inline int CursesWindow::lines() { return LINES; } inline int CursesWindow::cols() { return COLS; } inline CursesWindow* CursesWindow::child() { return subwins; } inline CursesWindow* CursesWindow::parent() { return par; } inline CursesWindow* CursesWindow::sibling() { return sib; } # endif sesWindow::standout() { return ::wstandout(w); } inline int CursesWindow::standend() { return ::wstandend(w); } inline int CursesWindow::lines() { return LINES; } inline int CursesWindow::cols() { return COLS; } inline CursesWindow* CursesWindow::child() libg++/g++-include/signal.h 644 473 0 4071 4677677766 10613 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _signal_h #pragma once extern "C" { // This #define KERNEL hack gets around bad function prototypes on most // systems. If not, you need to do some real work... #define KERNEL #include #undef KERNEL #ifndef _signal_h #define _signal_h 1 #endif // The Interviews folks call this SignalHandler. Might as well conform. // Beware: some systems think that SignalHandler returns int. typedef void (*SignalHandler) (...); extern SignalHandler signal(int sig, SignalHandler action); extern SignalHandler sigset(int sig, SignalHandler action); extern SignalHandler ssignal(int sig, SignalHandler action); extern int gsignal (int sig); extern int kill (int pid, int sig); #ifndef hpux // Interviews folks claim that hpux doesn't like these extern int sigsetmask(int mask); extern int sigblock(int mask); extern int sigpause(int mask); extern int sigvec(int sig, struct sigvec* v, struct sigvec* prev); #endif // The Interviews version also has these ... #define SignalBad ((SignalHandler)-1) #define SignalDefault ((SignalHandler)0) #define SignalIgnore ((SignalHandler)1) } #endif nt sig); extern int kill (int pid, int sig); #ifndef hpux // Interviews folks claim that hpux doesn't like these extern int sigsetmask(int mask); extern int sigblock(int mask); extern int sigpause(int mask); extern int sigvec(int sig, struct sigvec* v, struct sigvec* prev); #endif // The Interviews version also has these ... #define SignalBad ((SignalHandler)-1) #define SignalDefault ((SignalHandlerlibg++/g++-include/math-68881.h 644 473 0 20402 4677677766 10777 /******************************************************************\ * * * last modified: 18 May 1989. * * * * Copyright (C) 1989 by Matthew Self. * * You may freely distribute verbatim copies of this software * * provided that this copyright notice is retained in all copies. * * You may distribute modifications to this software under the * * conditions above if you also clearly note such modifications * * with their author and date. * * * * Note: errno is not set to EDOM when domain errors occur for * * most of these functions. Rather, it is assumed that the * * 68881's OPERR exception will be enabled and handled * * appropriately by the operating system. Similarly, overflow * * and underflow do not set errno to ERANGE. * * * * Send bugs to Matthew Self (self@bayes.arc.nasa.gov). * * * \******************************************************************/ #include #ifndef HUGE_VAL #define HUGE_VAL \ ({ \ double huge_val; \ \ __asm ("fmove%.d #0x7ff0000000000000,%0" /* Infinity */ \ : "=f" (huge_val) \ : /* no inputs */); \ huge_val; \ }) #endif __inline static const double sin (double x) { double value; __asm ("fsin%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double cos (double x) { double value; __asm ("fcos%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double tan (double x) { double value; __asm ("ftan%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double asin (double x) { double value; __asm ("fasin%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double acos (double x) { double value; __asm ("facos%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double atan (double x) { double value; __asm ("fatan%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double atan2 (double y, double x) { double pi, pi_over_2; __asm ("fmovecr%.x %#0,%0" /* extended precision pi */ : "=f" (pi) : /* no inputs */ ); __asm ("fscale%.b %#-1,%0" /* no loss of accuracy */ : "=f" (pi_over_2) : "0" (pi)); if (x > 0) { if (y > 0) { if (x > y) return atan (y / x); else return pi_over_2 - atan (x / y); } else { if (x > -y) return atan (y / x); else return - pi_over_2 - atan (x / y); } } else { if (y > 0) { if (-x > y) return pi + atan (y / x); else return pi_over_2 - atan (x / y); } else { if (-x > -y) return - pi + atan (y / x); else if (y < 0) return - pi_over_2 - atan (x / y); else { double value; errno = EDOM; __asm ("fmove%.d %#0rnan,%0" /* quiet NaN */ : "=f" (value) : /* no inputs */); return value; } } } } __inline static const double sinh (double x) { double value; __asm ("fsinh%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double cosh (double x) { double value; __asm ("fcosh%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double tanh (double x) { double value; __asm ("ftanh%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double atanh (double x) { double value; __asm ("fatanh%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double exp (double x) { double value; __asm ("fetox%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double expm1 (double x) { double value; __asm ("fetoxm1%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double log (double x) { double value; __asm ("flogn%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double log1p (double x) { double value; __asm ("flognp1%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double log10 (double x) { double value; __asm ("flog10%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double sqrt (double x) { double value; __asm ("fsqrt%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double pow (const double x, const double y) { if (x > 0) return exp (y * log (x)); else if (x == 0) { if (y > 0) return 0.0; else { double value; errno = EDOM; __asm ("fmove%.d %#0rnan,%0" /* quiet NaN */ : "=f" (value) : /* no inputs */); return value; } } else { double temp; __asm ("fintrz%.x %1,%0" : "=f" (temp) /* integer-valued float */ : "f" (y)); if (y == temp) { int i = (int) y; if ((i & 1) == 0) /* even */ return exp (y * log (x)); else return - exp (y * log (x)); } else { double value; errno = EDOM; __asm ("fmove%.d %#0rnan,%0" /* quiet NaN */ : "=f" (value) : /* no inputs */); return value; } } } __inline static const double fabs (double x) { double value; __asm ("fabs%.x %1,%0" : "=f" (value) : "f" (x)); return value; } __inline static const double ceil (double x) { int rounding_mode, round_up; double value; __asm volatile ("fmove%.l fpcr,%0" : "=dm" (rounding_mode) : /* no inputs */ ); round_up = rounding_mode | 0x30; __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (round_up)); __asm volatile ("fint%.x %1,%0" : "=f" (value) : "f" (x)); __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (rounding_mode)); return value; } __inline static const double floor (double x) { int rounding_mode, round_down; double value; __asm volatile ("fmove%.l fpcr,%0" : "=dm" (rounding_mode) : /* no inputs */ ); round_down = (rounding_mode & ~0x10) | 0x20; __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (round_down)); __asm volatile ("fint%.x %1,%0" : "=f" (value) : "f" (x)); __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (rounding_mode)); return value; } __inline static const double rint (double x) { int rounding_mode, round_nearest; double value; __asm volatile ("fmove%.l fpcr,%0" : "=dm" (rounding_mode) : /* no inputs */ ); round_nearest = rounding_mode & ~0x30; __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (round_nearest)); __asm volatile ("fint%.x %1,%0" : "=f" (value) : "f" (x)); __asm volatile ("fmove%.l %0,fpcr" : /* no outputs */ : "dmi" (rounding_mode)); return value; } __inline static const double fmod (double x, double y) { double value; __asm ("fmod%.x %2,%0" : "=f" (value) : "0" (x), "f" (y)); return value; } __inline static const double drem (double x, double y) { double value; __asm ("frem%.x %2,%0" : "=f" (value) : "0" (x), "f" (y)); return value; } __inline static const double scalb (double x, int n) { double value; __asm ("fscale%.l %2,%0" : "=f" (value) : "0" (x), "dmi" (n)); return value; } __inline static double logb (double x) { double exponent; __asm ("fgetexp%.x %1,%0" : "=f" (exponent) : "f" (x)); return exponent; } __inline static const double ldexp (double x, int n) { double value; __asm ("fscale%.l %2,%0" : "=f" (value) : "0" (x), "dmi" (n)); return value; } __inline static double frexp (double x, int *exp) { double float_exponent; int int_exponent; double mantissa; __asm ("fgetexp%.x %1,%0" : "=f" (float_exponent) /* integer-valued float */ : "f" (x)); int_exponent = (int) float_exponent; __asm ("fgetman%.x %1,%0" : "=f" (mantissa) /* 1.0 <= mantissa < 2.0 */ : "f" (x)); if (mantissa != 0) { __asm ("fscale%.b %#-1,%0" : "=f" (mantissa) /* mantissa /= 2.0 */ : "0" (mantissa)); int_exponent += 1; } *exp = int_exponent; return mantissa; } __inline static double modf (double x, double *ip) { double temp; __asm ("fintrz%.x %1,%0" : "=f" (temp) /* integer-valued float */ : "f" (x)); *ip = temp; return x - temp; } nt) float_exponent; __asm ("fgetman%.x %1,%0" : "=f" (mantissa) /* 1.0 <= mantissa < 2.0 */ : "f" (x)); if (mantissa != 0) { __asm ("fscale%.b %#-1,%0" : "=f" (mantissa) /* mantissa /= 2.0 */ : "0" (mantissa)); int_elibg++/g++-include/Fix16.h 644 473 0 30545 4677677766 10260 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Fix16_h #pragma once #define _Fix16_h 1 #include #include // constant definitions #define Fix16_fs ((double)((unsigned)(1 << 15))) #define Fix16_msb (1 << 15) #define Fix16_m_max ((1 << 15) - 1) #define Fix16_m_min ((short)(1 << 15)) #define Fix16_mult Fix16_fs #define Fix16_div (1./Fix16_fs) #define Fix16_max (1. - .5/Fix16_fs) #define Fix16_min (-1.) #define Fix32_fs ((double)((unsigned long)(1 << 31))) #define Fix32_msb ((unsigned long)(1 << 31)) #define Fix32_m_max ((1 << 31) - 1) #define Fix32_m_min ((long)(1 << 31)) #define Fix32_mult Fix32_fs #define Fix32_div (1./Fix32_fs) #define Fix32_max (1. - .5/Fix32_fs) #define Fix32_min (-1.) // // Fix16 class: 16-bit Fixed point data type // // consists of a 16-bit mantissa (sign bit & 15 data bits). // class Fix16 { friend class Fix32; short m; short round(double d); short assign(double d); Fix16(short i); Fix16(int i); operator double(); public: Fix16(); Fix16(Fix16& f); Fix16(double d); Fix16(Fix32& f); ~Fix16(); Fix16& operator=(Fix16& f); Fix16& operator=(double d); Fix16& operator=(Fix32& f); friend short& mantissa(Fix16& f); friend double value(Fix16& f); Fix16 operator + (); Fix16 operator - (); friend Fix16 operator + (Fix16& f, Fix16& g); friend Fix16 operator - (Fix16& f, Fix16& g); friend Fix32 operator * (Fix16& f, Fix16& g); friend Fix16 operator / (Fix16& f, Fix16& g); friend Fix16 operator << (Fix16& f, int b); friend Fix16 operator >> (Fix16& f, int b); Fix16& operator += (Fix16& f); Fix16& operator -= (Fix16& f); Fix16& operator *= (Fix16& ); Fix16& operator /= (Fix16& f); Fix16& operator <<=(int b); Fix16& operator >>=(int b); friend int operator == (Fix16& f, Fix16& g); friend int operator != (Fix16& f, Fix16& g); friend int operator >= (Fix16& f, Fix16& g); friend int operator <= (Fix16& f, Fix16& g); friend int operator > (Fix16& f, Fix16& g); friend int operator < (Fix16& f, Fix16& g); friend istream& operator >> (istream& s, Fix16& f); friend ostream& operator << (ostream& s, Fix16& f); void overflow(short&); void range_error(short&); friend Fix16 operator * (Fix16& f, int g); friend Fix16 operator * (int g, Fix16& f); Fix16& operator *= (int g); }; // // Fix32 class: 32-bit Fixed point data type // // consists of a 32-bit mantissa (sign bit & 31 data bits). // class Fix32 { friend class Fix16; long m; long round(double d); long assign(double d); Fix32(long i); operator double(); public: Fix32(); Fix32(Fix32& f); Fix32(Fix16& f); Fix32(double d); ~Fix32(); Fix32& operator = (Fix32& f); Fix32& operator = (Fix16& f); Fix32& operator = (double d); friend long& mantissa(Fix32& f); friend double value(Fix32& f); Fix32 operator + (); Fix32 operator - (); friend Fix32 operator + (Fix32& f, Fix32& g); friend Fix32 operator - (Fix32& f, Fix32& g); friend Fix32 operator * (Fix32& f, Fix32& g); friend Fix32 operator / (Fix32& f, Fix32& g); friend Fix32 operator << (Fix32& f, int b); friend Fix32 operator >> (Fix32& f, int b); friend Fix32 operator * (Fix16& f, Fix16& g); Fix32& operator += (Fix32& f); Fix32& operator -= (Fix32& f); Fix32& operator *= (Fix32& f); Fix32& operator /= (Fix32& f); Fix32& operator <<=(int b); Fix32& operator >>=(int b); friend int operator == (Fix32& f, Fix32& g); friend int operator != (Fix32& f, Fix32& g); friend int operator >= (Fix32& f, Fix32& g); friend int operator <= (Fix32& f, Fix32& g); friend int operator > (Fix32& f, Fix32& g); friend int operator < (Fix32& f, Fix32& g); friend istream& operator >> (istream& s, Fix32& f); friend ostream& operator << (ostream& s, Fix32& f); void overflow(long& i); void range_error(long& i); friend Fix32 operator * (Fix32& f, int g); friend Fix32 operator * (int g, Fix32& f); Fix32& operator *= (int g); }; inline Fix16::~Fix16() {} inline short Fix16::round(double d) { return short( (d >= 0)? d + 0.5 : d - 0.5); } inline Fix16::Fix16(short i) { m = i; } inline Fix16::Fix16(int i) { m = i; } inline Fix16::operator double() { return Fix16_div * m; } inline Fix16::Fix16() { m = 0; } inline Fix16::Fix16(Fix16& f) { m = f.m; } inline Fix16::Fix16(double d) { m = assign(d); } inline Fix16& Fix16::operator=(Fix16& f) { m = f.m; return *this; } inline Fix16& Fix16::operator=(double d) { m = assign(d); return *this; } inline Fix32::Fix32() { m = 0; } inline Fix32::Fix32(long i) { m = i; } inline Fix32:: operator double() { return Fix32_div * m; } inline Fix32::Fix32(Fix32& f) { m = f.m; } inline Fix32::Fix32(Fix16& f) { m = long(f.m) << 16; } inline Fix32::Fix32(double d) { m = assign(d); } inline Fix16::Fix16(Fix32& f) { m = f.m >> 16; } inline Fix16& Fix16::operator=(Fix32& f) { m = f.m >> 16; return *this; } inline Fix32& Fix32::operator=(Fix32& f) { m = f.m; return *this; } inline Fix32& Fix32::operator=(Fix16& f) { m = long(f.m) << 16; return *this; } inline Fix32& Fix32::operator=(double d) { m = assign(d); return *this; } inline short& mantissa(Fix16& f) { return f.m; } inline double value(Fix16& f) { return double(f); } inline Fix16 Fix16::operator+() { return m; } inline Fix16 Fix16::operator-() { return -m; } inline Fix16 operator+(Fix16& f, Fix16& g) { short sum = f.m + g.m; if ( (f.m ^ sum) & (g.m ^ sum) & Fix16_msb ) f.overflow(sum); return sum; } inline Fix16 operator-(Fix16& f, Fix16& g) { short sum = f.m - g.m; if ( (f.m ^ sum) & (-g.m ^ sum) & Fix16_msb ) f.overflow(sum); return sum; } inline Fix32 operator*(Fix16& f, Fix16& g) { return Fix32( long( long(f.m) * long(g.m) << 1)); } inline Fix16 operator<<(Fix16& a, int b) { return a.m << b; } inline Fix16 operator>>(Fix16& a, int b) { return a.m >> b; } inline Fix16& Fix16:: operator+=(Fix16& f) { return *this = *this + f; } inline Fix16& Fix16:: operator-=(Fix16& f) { return *this = *this - f; } inline Fix16& Fix16::operator*=(Fix16& f) { return *this = *this * f; } inline Fix16& Fix16:: operator/=(Fix16& f) { return *this = *this / f; } inline Fix16& Fix16:: operator<<=(int b) { return *this = *this << b; } inline Fix16& Fix16:: operator>>=(int b) { return *this = *this >> b; } inline int operator==(Fix16& f, Fix16& g) { return f.m == g.m; } inline int operator!=(Fix16& f, Fix16& g) { return f.m != g.m; } inline int operator>=(Fix16& f, Fix16& g) { return f.m >= g.m; } inline int operator<=(Fix16& f, Fix16& g) { return f.m <= g.m; } inline int operator>(Fix16& f, Fix16& g) { return f.m > g.m; } inline int operator<(Fix16& f, Fix16& g) { return f.m < g.m; } inline istream& operator>>(istream& s, Fix16& f) { double d; s >> d; f = d; return s; } inline ostream& operator<<(ostream& s, Fix16& f) { return s << double(f); } inline Fix16 operator*(Fix16& f, int g) { return Fix16(short(f.m * g)); } inline Fix16 operator*(int g, Fix16& f) { return f * g; } inline Fix16& Fix16::operator*=(int g) { return *this = *this * g; } inline Fix32::~Fix32() {} inline long Fix32::round(double d) { return long( (d >= 0)? d + 0.5 : d - 0.5); } inline long& mantissa(Fix32& f) { return f.m; } inline double value(Fix32& f) { return double(f); } inline Fix32 Fix32::operator+() { return m; } inline Fix32 Fix32::operator-() { return -m; } inline Fix32 operator+(Fix32& f, Fix32& g) { long sum = f.m + g.m; if ( (f.m ^ sum) & (g.m ^ sum) & Fix32_msb ) f.overflow(sum); return sum; } inline Fix32 operator-(Fix32& f, Fix32& g) { long sum = f.m - g.m; if ( (f.m ^ sum) & (-g.m ^ sum) & Fix32_msb ) f.overflow(sum); return sum; } inline Fix32 operator<<(Fix32& a, int b) { return a.m << b; } inline Fix32 operator>>(Fix32& a, int b) { return a.m >> b; } inline Fix32& Fix32::operator+=(Fix32& f) { return *this = *this + f; } inline Fix32& Fix32::operator-=(Fix32& f) { return *this = *this - f; } inline Fix32& Fix32::operator*=(Fix32& f) { return *this = *this * f; } inline Fix32& Fix32::operator/=(Fix32& f) { return *this = *this / f; } inline Fix32& Fix32::operator<<=(int b) { return *this = *this << b; } inline Fix32& Fix32::operator>>=(int b) { return *this = *this >> b; } inline int operator==(Fix32& f, Fix32& g) { return f.m == g.m; } inline int operator!=(Fix32& f, Fix32& g) { return f.m != g.m; } inline int operator>=(Fix32& f, Fix32& g) { return f.m >= g.m; } inline int operator<=(Fix32& f, Fix32& g) { return f.m <= g.m; } inline int operator>(Fix32& f, Fix32& g) { return f.m > g.m; } inline int operator<(Fix32& f, Fix32& g) { return f.m < g.m; } inline istream& operator>>(istream& s, Fix32& f) { double d; s >> d; f = d; return s; } inline ostream& operator<<(ostream& s, Fix32& f) { return s << double(f); } inline Fix32 operator*(Fix32& f, int g) { return Fix32(long(f.m * g)); } inline Fix32 operator*(int g, Fix32& f) { return f * g; } inline Fix32& Fix32::operator*=(int g) { return *this = *this * g; } // active error handler declarations typedef void (*Fix16_peh)(short&); typedef void (*Fix32_peh)(long&); extern Fix16_peh Fix16_overflow_handler; extern Fix32_peh Fix32_overflow_handler; extern Fix16_peh Fix16_range_error_handler; extern Fix32_peh Fix32_range_error_handler; // error handler declarations extern Fix16_peh set_Fix16_overflow_handler(Fix16_peh); extern Fix32_peh set_Fix32_overflow_handler(Fix32_peh); extern void set_overflow_handler(Fix16_peh, Fix32_peh); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handler(Fix16_peh, Fix32_peh); extern void Fix16_ignore(short&), Fix16_overflow_saturate(short&), Fix16_overflow_warning_saturate(short&), Fix16_warning(short&), Fix16_abort(short&); extern void Fix32_ignore(long&), Fix32_overflow_saturate(long&), Fix32_overflow_warning_saturate(long&), Fix32_warning(long&), Fix32_abort(long&); #endif ); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handllibg++/g++-include/bstring.h 644 473 0 36 4677677766 10743 #pragma once #include ern void Fix16_ignore(short&), Fix16_overflow_saturate(short&), Fix16_overflow_warning_saturate(short&), Fix16_warning(short&), Fix16_abort(short&); extern void Fix32_ignore(long&), Fix32_overflow_saturate(long&), Fix32_overflow_warning_saturate(long&), Fix32_warning(long&), Fix32_abort(long&); #endif ); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handllibg++/g++-include/memory.h 644 473 0 36 4677677767 10604 #pragma once #include ern void Fix16_ignore(short&), Fix16_overflow_saturate(short&), Fix16_overflow_warning_saturate(short&), Fix16_warning(short&), Fix16_abort(short&); extern void Fix32_ignore(long&), Fix32_overflow_saturate(long&), Fix32_overflow_warning_saturate(long&), Fix32_warning(long&), Fix32_abort(long&); #endif ); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handllibg++/g++-include/file.h 644 473 0 72 4677677767 10213 #ifndef file_h #pragma once #include #endif t&), Fix16_overflow_saturate(short&), Fix16_overflow_warning_saturate(short&), Fix16_warning(short&), Fix16_abort(short&); extern void Fix32_ignore(long&), Fix32_overflow_saturate(long&), Fix32_overflow_warning_saturate(long&), Fix32_warning(long&), Fix32_abort(long&); #endif ); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handllibg++/g++-include/random.h 644 473 0 36 4677677767 10554 #pragma once #include include #endif t&), Fix16_overflow_saturate(short&), Fix16_overflow_warning_saturate(short&), Fix16_warning(short&), Fix16_abort(short&); extern void Fix32_ignore(long&), Fix32_overflow_saturate(long&), Fix32_overflow_warning_saturate(long&), Fix32_warning(long&), Fix32_abort(long&); #endif ); extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); extern void set_range_error_handllibg++/g++-include/unistd.h 644 473 0 1422 4677677770 10634 #ifndef unistd_h #pragma once #define unistd_h 1 #include /* A safe-looking set of things from various system versions */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef GF_PATH #define GF_PATH "/etc/group" #endif #ifndef PF_PATH #define PF_PATH "/etc/passwd" #endif #ifndef IN_PATH #define IN_PATH "/usr/include" #endif #ifndef R_OK #define R_OK 4 #endif #ifndef W_OK #define W_OK 2 #endif #ifndef X_OK #define X_OK 1 #endif #ifndef F_OK #define F_OK 0 #endif #ifndef NULL #define NULL 0 #endif #ifndef F_ULOCK #define F_ULOCK 0 #endif #ifndef F_LOCK #define F_LOCK 1 #endif #ifndef F_TLOCK #define F_TLOCK 2 #endif #ifndef F_TEST #define F_TEST 3 #endif #endif ndef GF_PATH #define GF_PATH "/etc/group" #endif #ifndef PF_PATH #define PF_PATH "/etc/passwd" #endif #ifndef IN_PATH #define IN_PATH "/usr/include" #endif #ifndef R_OK #define R_OK 4 #endif #ifndef W_OK #define W_OK 2 #endif #ifndeflibg++/g++-include/grp.h 644 473 0 1207 4677677770 10117 #ifndef grp_h #pragma once #include extern "C" { #define getgrent c_proto_getgrent #define getgrgid c_proto_getgrgid #define getgrnam c_proto_getgrnam #define setgrent c_proto_setgrent #define endgrent c_proto_endgrent #define fgetgrent c_proto_fgetgrent #define KERNEL #include "//usr/include/grp.h" #ifndef grp_h #define grp_h 1 #endif #undef getgrent #undef getgrgid #undef getgrnam #undef KERNEL extern struct group* getgrent(); extern struct group* fgetgrent(FILE*); extern struct group* getgrgid(int); extern struct group* getgrnam(const char*); extern void setgrent(); extern void endgrent(); } #endif ne getgrnam c_proto_getgrnam #define setgrent c_proto_setgrent #define endgrent c_proto_endgrent #define fgetgrent c_proto_fgetgrent #define KERNEL #include "//usr/include/grp.h" #ifndef grp_h #define grp_h 1 #endif #undef getgrent #undef getgrgid #undef getgrnam #undef KERNEL extern struct group* getgrent(); extern struct group* fgetgrent(FILE*); extern struct group* glibg++/g++-include/errno.h 644 473 0 222 4677677770 10430 #ifndef errno_h #pragma once extern "C" { #include "//usr/include/errno.h" } #ifndef errno_h #define errno_h 1 #endif #include #endif c_proto_getgrnam #define setgrent c_proto_setgrent #define endgrent c_proto_endgrent #define fgetgrent c_proto_fgetgrent #define KERNEL #include "//usr/include/grp.h" #ifndef grp_h #define grp_h 1 #endif #undef getgrent #undef getgrgid #undef getgrnam #undef KERNEL extern struct group* getgrent(); extern struct group* fgetgrent(FILE*); extern struct group* glibg++/g++-include/time.h 644 473 0 3253 4677677770 10270 #ifndef time_h #define time_h 1 // this kludge will probably work on most systems #include /* sorry, but needed for DGUX */ #include /* sorry, but needed for USG */ #include extern "C" { #define gmtime c_proto_gmtime #define localtime c_proto_localtime #define asctime c_proto_asctime #define ctime c_proto_ctime #define tzset c_proto_tzset #define tzsetwall c_proto_tzsetwall #define timezone c_proto_timezone #define getitimer c_proto_getitimer #define setitimer c_proto_setitimer #define gettimeofday c_proto_gettimeofday #define settimeofday c_proto_settimeofday #define KERNEL #ifndef USG #include "//usr/include/sys/time.h" #endif #include "//usr/include/sys/times.h" #include "//usr/include/time.h" #undef KERNEL #undef gmtime #undef localtime #undef asctime #undef ctime #undef tzset #undef tzsetwall #undef timezone #undef getitimer #undef setitimer #undef gettimeofday #undef settimeofday extern struct tm* localtime(long*); extern struct tm* gmtime(long*); extern char* ctime(long*); extern char* asctime(struct tm*); extern void tzset(); extern void tzsetwall(); extern long times(struct tms*); #if defined(USG) extern long timezone; extern int daylight; extern char* tzname[]; #else typedef struct c_proto_timezone timezone; extern char* timezone(int, int); extern int getitimer(int, struct itimerval*); extern int setitimer(int, struct itimerval*, struct itimerval*); extern int gettimeofday(struct timeval*, struct timezone*); extern int settimeofday(struct timeval*, struct timezone*); #endif } #else #ifdef ctime /* What to do if "//usr/include/sys/time.h" tries to include us. */ #include "//usr/include/time.h" #endif #endif imezone; extern int daylight; extern char* tzname[]; #else typedef struct c_proto_timezone timezone; extern char* timezone(int, int); extern int getitimer(int, struct itimerval*); extern int setitimer(int, struct itimerval*, struct itimerval*); extern int gettimeofday(struct timeval*, struct timezone*); extern int settimeofday(struct timevlibg++/g++-include/pwd.h 644 473 0 1165 4677677770 10124 #ifndef pwd_h #pragma once // the Interviews-based standard kludge again extern "C" { #define getpwent c_proto_getpwent #define getpwuid c_proto_getpwuid #define getpwnam c_proto_getpwnam #define setpwent c_proto_setpwent #define endpwent c_proto_endpwent #define KERNEL #include "//usr/include/pwd.h" #ifndef pwd_h #define pwd_h 1 #endif #undef getpwent #undef getpwuid #undef getpwnam #undef setpwent #undef endpwent #undef KERNEL extern struct passwd* getpwent(); extern struct passwd* getpwuid(int); extern struct passwd* getpwnam(char*); extern int setpwent(); extern int endpwent(); } #endif pwent #define getpwuid c_proto_getpwuid #define getpwnam c_proto_getpwnam #define setpwent c_proto_setpwent #define endpwent c_proto_endpwent #define KERNEL #include "//usr/include/pwd.h" #ifndef pwd_h #define pwd_h 1 #endif #undef getpwent #undef getpwuid #undef getpwnam #undef setpwent #undef endpwent #undef KERNEL extern struct passwd* getpwent(); extern struct passwd* getpwuid(int); elibg++/g++-include/RAVLMap.hP 644 473 0 6727 4677677771 10666 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) ranking code from Paul Anderson (paul%lfcs.ed.ac.uk) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RAVLMap_h #pragma once #define _RAVLMap_h 1 #include "..Map.h" struct RAVLNode { RAVLNode* lt; RAVLNode* rt; item; cont; int rank; char stat; RAVLNode( h, c, RAVLNode* l=0, RAVLNode* r=0, int k=1); ~RAVLNode(); }; inline RAVLNode::RAVLNode( h, c, RAVLNode* l=0, RAVLNode* r=0, int k=1) :item(h), cont(c), lt(l), rt(r), rank(k) { stat = 0; } inline RAVLNode::~RAVLNode() {} typedef RAVLNode* RAVLNodePtr; class RAVLMap : public Map { protected: RAVLNode* root; RAVLNode* leftmost(); RAVLNode* rightmost(); RAVLNode* pred(RAVLNode* t); RAVLNode* succ(RAVLNode* t); void _kill(RAVLNode* t); void _add(RAVLNode*& t); void _del(RAVLNode* p, RAVLNode*& t); public: RAVLMap( dflt); RAVLMap(RAVLMap& a); ~RAVLMap(); & operator [] ( key); void del( key); Pix first(); void next(Pix& i); & key(Pix i); & contents(Pix i); Pix seek( key); int contains( key); Pix ranktoPix(int i); int rankof( key); void clear(); Pix last(); void prev(Pix& i); int OK(); }; inline RAVLMap::~RAVLMap() { _kill(root); } inline RAVLMap::RAVLMap( dflt) :(dflt) { root = 0; } inline Pix RAVLMap::first() { return Pix(leftmost()); } inline Pix RAVLMap::last() { return Pix(rightmost()); } inline void RAVLMap::next(Pix& i) { if (i != 0) i = Pix(succ((RAVLNode*)i)); } inline void RAVLMap::prev(Pix& i) { if (i != 0) i = Pix(pred((RAVLNode*)i)); } inline & RAVLMap::key(Pix i) { if (i == 0) error("null Pix"); return ((RAVLNode*)i)->item; } inline & RAVLMap::contents(Pix i) { if (i == 0) error("null Pix"); return ((RAVLNode*)i)->cont; } inline void RAVLMap::clear() { _kill(root); count = 0; root = 0; } inline int RAVLMap::contains( key) { return seek(key) != 0; } #endif T>RAVLNode*)i)); } inline void libg++/g++-include/RAVLMap.ccP 644 473 0 34025 4677677771 11034 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include "..RAVLMap.h" /* constants & inlines for maintaining balance & thread status in tree nodes */ #define AVLBALANCEMASK 3 #define AVLBALANCED 0 #define AVLLEFTHEAVY 1 #define AVLRIGHTHEAVY 2 #define LTHREADBIT 4 #define RTHREADBIT 8 static inline int bf(RAVLNode* t) { return t->stat & AVLBALANCEMASK; } static inline void set_bf(RAVLNode* t, int b) { t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); } static inline int rthread(RAVLNode* t) { return t->stat & RTHREADBIT; } static inline void set_rthread(RAVLNode* t, int b) { if (b) t->stat |= RTHREADBIT; else t->stat &= ~RTHREADBIT; } static inline int lthread(RAVLNode* t) { return t->stat & LTHREADBIT; } static inline void set_lthread(RAVLNode* t, int b) { if (b) t->stat |= LTHREADBIT; else t->stat &= ~LTHREADBIT; } /* traversal primitives */ RAVLNode* RAVLMap::leftmost() { RAVLNode* t = root; if (t != 0) while (t->lt != 0) t = t->lt; return t; } RAVLNode* RAVLMap::rightmost() { RAVLNode* t = root; if (t != 0) while (t->rt != 0) t = t->rt; return t; } RAVLNode* RAVLMap::succ(RAVLNode* t) { RAVLNode* r = t->rt; if (!rthread(t)) while (!lthread(r)) r = r->lt; return r; } RAVLNode* RAVLMap::pred(RAVLNode* t) { RAVLNode* l = t->lt; if (!lthread(t)) while (!rthread(l)) l = l->rt; return l; } Pix RAVLMap::seek( key) { RAVLNode* t = root; if (t == 0) return 0; for (;;) { int cmp = CMP(key, t->item); if (cmp == 0) return Pix(t); else if (cmp < 0) { if (lthread(t)) return 0; else t = t->lt; } else if (rthread(t)) return 0; else t = t->rt; } } int RAVLMap::rankof( key) { int r; RAVLNode* t = root; if (t == 0) return 0; for (r=t->rank; t != 0; r+=t->rank) { int cmp = CMP(key, t->item); if (cmp == 0) return r; else if (cmp < 0) { if (lthread(t)) return 0; else { r -= t->rank; t = t->lt; } } else if (rthread(t)) return 0; else { t = t->rt; } } return 0; } Pix RAVLMap::ranktoPix(int i) { int r; RAVLNode* t = root; if ((i<1)||(i>count)) return 0; for (r=t->rank; r!=i; r+=t->rank) { if (r>i) { r -= t->rank; t = t->lt; } else t = t->rt; } return Pix(t); } /* The combination of threads and AVL bits make adding & deleting interesting, but very awkward. We use the following statics to avoid passing them around recursively */ static int _need_rebalancing; // to send back balance info from rec. calls static * _target_item; // add/del_item target static RAVLNode* _found_node; // returned added/deleted node static int _already_found; // for deletion subcases static int _rank_changed; // for rank computation void RAVLMap:: _add(RAVLNode*& t) { int cmp = CMP(*_target_item, t->item); if (cmp == 0) { _found_node = t; return; } else if (cmp < 0) { if (lthread(t)) { ++count; _found_node = new RAVLNode(*_target_item, def); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t->lt; _found_node->rt = t; t->lt = _found_node; set_lthread(t, 0); _need_rebalancing = 1; _rank_changed = 1; } else _add(t->lt); if (_rank_changed) ++t->rank; if (_need_rebalancing) { switch(bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); return; case AVLLEFTHEAVY: RAVLNode* l = t->lt; if (bf(l) == AVLLEFTHEAVY) { t->rank -= l->rank; if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; } else { RAVLNode* r = l->rt; r->rank += l->rank; t->rank -= r->rank; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; return; } } } } else { if (rthread(t)) { ++count; _found_node = new RAVLNode(*_target_item, def); set_rthread(t, 0); set_lthread(_found_node, 1); set_rthread(_found_node, 1); _found_node->lt = t; _found_node->rt = t->rt; t->rt = _found_node; _need_rebalancing = 1; _rank_changed = 1; } else _add(t->rt); if (_need_rebalancing) { switch(bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); _need_rebalancing = 0; return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); return; case AVLRIGHTHEAVY: RAVLNode* r = t->rt; if (bf(r) == AVLRIGHTHEAVY) { r->rank += t->rank; if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; _need_rebalancing = 0; } else { RAVLNode* l = r->lt; r->rank -= l->rank; l->rank += t->rank; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; _need_rebalancing = 0; return; } } } } } & RAVLMap::operator [] ( item) { if (root == 0) { ++count; root = new RAVLNode(item, def); set_rthread(root, 1); set_lthread(root, 1); return root->cont; } else { _target_item = &item; _need_rebalancing = 0; _rank_changed = 0; _add(root); return _found_node->cont; } } void RAVLMap::_del(RAVLNode* par, RAVLNode*& t) { int comp; if (_already_found) { if (rthread(t)) comp = 0; else comp = 1; } else comp = CMP(*_target_item, t->item); if (comp == 0) { if (lthread(t) && rthread(t)) { _found_node = t; if (t == par->lt) { set_lthread(par, 1); par->lt = t->lt; } else { set_rthread(par, 1); par->rt = t->rt; } _need_rebalancing = 1; _rank_changed = 1; return; } else if (lthread(t)) { _found_node = t; RAVLNode* s = succ(t); if (s != 0 && lthread(s)) s->lt = t->lt; t = t->rt; _need_rebalancing = 1; _rank_changed = 1; return; } else if (rthread(t)) { _found_node = t; RAVLNode* p = pred(t); if (p != 0 && rthread(p)) p->rt = t->rt; t = t->lt; _need_rebalancing = 1; _rank_changed = 1; return; } else // replace item & find someone deletable { RAVLNode* p = pred(t); t->item = p->item; t->cont = p->cont; _already_found = 1; comp = -1; // fall through below to left } } if (comp < 0) { if (lthread(t)) return; _del(t, t->lt); if (_rank_changed) --t->rank; if (!_need_rebalancing) return; switch (bf(t)) { case AVLLEFTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLRIGHTHEAVY); _need_rebalancing = 0; return; case AVLRIGHTHEAVY: RAVLNode* r = t->rt; switch (bf(r)) { case AVLBALANCED: r->rank += t->rank; if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLRIGHTHEAVY); set_bf(r, AVLLEFTHEAVY); _need_rebalancing = 0; t = r; return; case AVLRIGHTHEAVY: r->rank += t->rank; if (lthread(r)) t->rt = r; else t->rt = r->lt; set_rthread(t, lthread(r)); r->lt = t; set_lthread(r, 0); set_bf(t, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; case AVLLEFTHEAVY: RAVLNode* l = r->lt; r->rank -= l->rank; l->rank += t->rank; set_lthread(r, rthread(l)); if (rthread(l)) r->lt = l; else r->lt = l->rt; l->rt = r; set_rthread(l, 0); set_rthread(t, lthread(l)); if (lthread(l)) t->rt = l; else t->rt = l->lt; l->lt = t; set_lthread(l, 0); if (bf(l) == AVLRIGHTHEAVY) set_bf(t, AVLLEFTHEAVY); else set_bf(t, AVLBALANCED); if (bf(l) == AVLLEFTHEAVY) set_bf(r, AVLRIGHTHEAVY); else set_bf(r, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; } } } else { if (rthread(t)) return; _del(t, t->rt); if (!_need_rebalancing) return; switch (bf(t)) { case AVLRIGHTHEAVY: set_bf(t, AVLBALANCED); return; case AVLBALANCED: set_bf(t, AVLLEFTHEAVY); _need_rebalancing = 0; return; case AVLLEFTHEAVY: RAVLNode* l = t->lt; switch (bf(l)) { case AVLBALANCED: t->rank -= l->rank; if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLLEFTHEAVY); set_bf(l, AVLRIGHTHEAVY); _need_rebalancing = 0; t = l; return; case AVLLEFTHEAVY: t->rank -= l->rank; if (rthread(l)) t->lt = l; else t->lt = l->rt; set_lthread(t, rthread(l)); l->rt = t; set_rthread(l, 0); set_bf(t, AVLBALANCED); set_bf(l, AVLBALANCED); t = l; return; case AVLRIGHTHEAVY: RAVLNode* r = l->rt; r->rank += l->rank; t->rank -= r->rank; set_rthread(l, lthread(r)); if (lthread(r)) l->rt = r; else l->rt = r->lt; r->lt = l; set_lthread(r, 0); set_lthread(t, rthread(r)); if (rthread(r)) t->lt = r; else t->lt = r->rt; r->rt = t; set_rthread(r, 0); if (bf(r) == AVLLEFTHEAVY) set_bf(t, AVLRIGHTHEAVY); else set_bf(t, AVLBALANCED); if (bf(r) == AVLRIGHTHEAVY) set_bf(l, AVLLEFTHEAVY); else set_bf(l, AVLBALANCED); set_bf(r, AVLBALANCED); t = r; return; } } } } void RAVLMap::del( item) { if (root == 0) return; _need_rebalancing = 0; _already_found = 0; _found_node = 0; _rank_changed = 0; _target_item = &item; _del(root, root); if (_found_node) { delete(_found_node); if (--count == 0) root = 0; } } void RAVLMap::_kill(RAVLNode* t) { if (t != 0) { if (!lthread(t)) _kill(t->lt); if (!rthread(t)) _kill(t->rt); delete t; } } RAVLMap::RAVLMap(RAVLMap& b) :(b.def) { root = 0; count = 0; for (Pix i = b.first(); i != 0; b.next(i)) (*this)[b.key(i)] = b.contents(i); } int RAVLMap::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; RAVLNode* trail = leftmost(); v &= rankof(trail->item) == n; RAVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; v &= rankof(t->item) == n; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant failure"); return v; } i != 0; b.next(i)) (*this)[b.key(i)] = b.contents(i); } int RAVLMap::OK() { int v = 1; if (root == 0) v = count == 0; else { int n = 1; RAVLNode* trail = leftmost(); v &= rankof(trail->item) == n; RAVLNode* t = succ(trail); while (t != 0) { ++n; v &= CMP(trail->item, t->item) < 0; v &= rankof(t->item) == n; trail = t; t = succ(t); } v &= n == count; } if (!v) error("invariant faillibg++/g++-include/AllocRing.h 644 473 0 3254 4677677771 11206 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _AllocRing_h #pragma once #define _AllocRing_h 1 /* An AllocRing holds the last n malloc'ed strings, reallocating/reusing one only when the queue wraps around. It thus guarantees that the last n allocations are intact. It is useful for things like I/O formatting where reasonable restrictions may be made about the number of allowable live allocations before auto-deletion. */ class AllocRing { struct AllocQNode { void* ptr; int sz; }; AllocQNode* nodes; int n; int current; int find(void* p); public: AllocRing(int max); ~AllocRing(); void* alloc(int size); int contains(void* ptr); void clear(); void free(void* p); }; #endif like I/O formatting where reasonable restrictions may be made about the number of allowable live allocations before auto-deletion. */ class AllocRing { struct AllocQNode { void* ptr; int sz; }; AllocQNode* nodes; int n; int current; int find(void* p); public: AllocRlibg++/g++-include/GetOpt.h 644 473 0 11232 4677677771 10551 /* Getopt for GNU. Copyright (C) 1987, 1989 Free Software Foundation, Inc. (Modified by Douglas C. Schmidt for use with GNU G++.) 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 1, 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. */ /* 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 _POSIX_OPTION_ORDER 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. */ #ifndef GetOpt_h #pragma once #define GetOpt_h 1 #include #include class GetOpt { private: /* 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; /* Describe how to deal with options that follow non-option ARGV-elements. UNSPECIFIED means the caller did not specify anything; the default is then REQUIRE_ORDER if the environment variable _OPTIONS_FIRST 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. PERMUTE is the default. We permute the contents of `argv' as we scan, so that eventually all the 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 zero. Using `-' as the first character of the list of option characters requests 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; /* 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; void exchange (char **argv); public: /* 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; /* 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. */ int optind; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr; int nargc; char **nargv; char *noptstring; GetOpt (int argc, char **argv, char *optstring); int operator () (void); }; #endif ns 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. */ int optind; /* Callers store zero here to inhibit the error message for unrecognized options. */ int olibg++/g++-include/stdlib.h 644 473 0 21 4677677772 10543 #include nargc; char **nargv; char *noptstring; GetOpt (int argc, char **argv, char *optstring); int operator () (void); }; #endif ns 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. */ int optind; /* Callers store zero here to inhibit the error message for unrecognized options. */ int olibg++/g++-include/getpagesize.h 644 473 0 727 4677677772 11626 #if defined(BSD) || defined(DGUX) #ifndef BSD4_1 #define HAVE_GETPAGESIZE #endif #endif #ifndef HAVE_GETPAGESIZE #include #ifdef EXEC_PAGESIZE #define getpagesize() EXEC_PAGESIZE #else #ifdef NBPG #define getpagesize() NBPG * CLSIZE #ifndef CLSIZE #define CLSIZE 1 #endif /* no CLSIZE */ #else /* no NBPG */ #ifdef NBPC #define getpagesize() NBPC #endif /* NBPC */ #endif /* no NBPG */ #endif /* no EXEC_PAGESIZE */ #endif /* not HAVE_GETPAGESIZE */ for unrecognized options. */ int olibg++/g++-include/malloc.h 644 473 0 21 4677677772 10531 #include || defined(DGUX) #ifndef BSD4_1 #define HAVE_GETPAGESIZE #endif #endif #ifndef HAVE_GETPAGESIZE #include #ifdef EXEC_PAGESIZE #define getpagesize() EXEC_PAGESIZE #else #ifdef NBPG #define getpagesize() NBPG * CLSIZE #ifndef CLSIZE #define CLSIZE 1 #endif /* no CLSIZE */ #else /* no NBPG */ #ifdef NBPC #define getpagesize() NBPC #endif /* NBPC */ #endif /* no NBPG */ #endif /* no EXEC_PAGESIZE */ #endif /* not HAVE_GETPAGESIZE */ for unrecognized options. */ int olibg++/g++-include/fcntl.h 644 473 0 263 4677677772 10420 #ifndef fcntl_h #pragma once extern "C" { #define KERNEL #include "//usr/include/fcntl.h" #ifndef fcntl_h #define fcntl_h 1 #endif #undef KERNEL } #include #endif ze() EXEC_PAGESIZE #else #ifdef NBPG #define getpagesize() NBPG * CLSIZE #ifndef CLSIZE #define CLSIZE 1 #endif /* no CLSIZE */ #else /* no NBPG */ #ifdef NBPC #define getpagesize() NBPC #endif /* NBPC */ #endif /* no NBPG */ #endif /* no EXEC_PAGESIZE */ #endif /* not HAVE_GETPAGESIZE */ for unrecognized options. */ int olibg++/g++-include/RandomInteger. 644 473 0 7312 4677677773 11723 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1990 Free Software Foundation adapted from a submission from John Reidl GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _RandomInteger_h #pragma once #define _RandomInteger_h 1 // RandomInteger uses a random number generator to generate an integer // in a specified range. By default the range is 0..1. Since in my // experience random numbers are often needed for a wide variety of // ranges in the same program, this generator accepts a new low or high value // as an argument to the asLong and operator() methods to temporarily // override stored values #include #include "RNG.h" class RandomInteger { protected: RNG *pGenerator; long pLow; long pHigh; long _asLong(long, long); public: RandomInteger(long low, long high, RNG *gen); RandomInteger(long high, RNG *gen); RandomInteger(RNG *gen); // read params long low() const; long high() const; RNG* generator() const; // change params long low(long x); long high(long x); RNG* generator(RNG *gen); // get a random number long asLong(); long operator()(); // synonym for asLong int asInt(); // (possibly) truncate as int // override params for one shot long asLong(long high); long asLong(long low, long high); long operator () (long high); // synonyms long operator () (long low, long high); }; inline RandomInteger::RandomInteger(long low, long high, RNG *gen) : pLow((low < high) ? low : high), pHigh((low < high) ? high : low), pGenerator(gen) {} inline RandomInteger::RandomInteger(long high, RNG *gen) : pLow((0 < high) ? 0 : high), pHigh((0 < high) ? high : 0), pGenerator(gen) {} inline RandomInteger::RandomInteger(RNG *gen) : pLow(0), pHigh(1), pGenerator(gen) {} inline RNG* RandomInteger::generator() const { return pGenerator;} inline long RandomInteger::low() const { return pLow; } inline long RandomInteger::high() const { return pHigh; } inline RNG* RandomInteger::generator(RNG *gen) { RNG *tmp = pGenerator; pGenerator = gen; return tmp; } inline long RandomInteger::low(long x) { long tmp = pLow; pLow = x; return tmp; } inline long RandomInteger:: high(long x) { long tmp = pHigh; pHigh = x; return tmp; } inline long RandomInteger:: _asLong(long low, long high) { return (pGenerator->asLong() % (high-low+1)) + low; } inline long RandomInteger:: asLong() { return _asLong(pLow, pHigh); } inline long RandomInteger:: asLong(long high) { return _asLong(pLow, high); } inline long RandomInteger:: asLong(long low, long high) { return _asLong(low, high); } inline long RandomInteger:: operator () () { return _asLong(pLow, pHigh); } inline long RandomInteger:: operator () (long high) { return _asLong(pLow, high); } inline long RandomInteger:: operator () (long low, long high) { return _asLong(low, high); } inline int RandomInteger:: asInt() { return int(asLong()); } #endif } inline long RandomInteger:: asLong(long high) { return _asLong(pLow, high); } inline long RandomInteger:: asLong(long low, long high) { return _asLong(low, high); } inline long RandomInteger:: operator () () { return _asLong(pLow, pHigh); } inline long RandomInteger:: operator () (long high) { libg++/g++-include/ostream.h 644 473 0 12600 4677677773 11023 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* *** Version 1.2 -- nearly 100% AT&T 1.2 compatible *** */ /* ostream.h now separately includable */ #ifndef _ostream_h #pragma once #define _ostream_h 1 /* uncomment the next line to disable ostream << char */ //#define NO_OUTPUT_CHAR #include #include class istream; class ostream { friend class istream; protected: streambuf* bp; state_value state; // _good/_eof/_fail/_bad char ownbuf; // true if we own *bp public: ostream(const char* filename, io_mode m, access_mode a); ostream(const char* filename, const char* m); ostream(int filedesc, io_mode m); ostream(FILE* fileptr); ostream(int sz, char* buf); ostream(int filedesc, char* buf, int buflen); ostream(int filedesc); ostream(streambuf* s); ~ostream(); ostream& open(const char* filename, io_mode m, access_mode a); ostream& open(const char* filename, const char* m); ostream& open(int filedesc, io_mode m); ostream& open(FILE* fileptr); ostream& open(const char* filenam, open_mode m); ostream& close(); ostream& flush(); // stream status int rdstate(); int eof(); int fail(); int bad(); int good(); // other status queries int readable(); int writable(); int is_open(); operator void*(); int operator !(); const char* name(); char* bufptr(); // error handling void error(); void clear(state_value f = _good); // poorly named void set(state_value f); // set corresponding bit void unset(state_value); // clear corresponding bit ostream& failif(int cond); // unformatted IO ostream& put(char c); ostream& put(const char* s); ostream& put(const char* s, int slen); // formatted IO ostream& form(const char* fmt, ...); ostream& operator << (short n); ostream& operator << (unsigned short n); ostream& operator << (int n); ostream& operator << (unsigned int n); ostream& operator << (long n); ostream& operator << (unsigned long n); #ifdef __GNUG__ ostream& operator << (long long n); ostream& operator << (unsigned long long n); #endif __GNUG__ ostream& operator << (float n); ostream& operator << (double n); ostream& operator << (const char* s); #ifndef NO_OUTPUT_CHAR ostream& operator << (char c); #endif }; extern ostream cout; // stdout extern ostream cerr; // stderr inline void ostream::clear(state_value flag) { state = flag; } inline void ostream::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void ostream::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int ostream::rdstate() { return int(state); } inline int ostream::good() { return state == _good; } inline int ostream::eof() { return int(state) & int(_eof); } inline int ostream::fail() { return int(state) & int(_fail); } inline int ostream::bad() { return int(state) & int(_bad); } inline ostream::operator void*() { return (state == _good)? this : 0; } inline int ostream::operator !() { return (state != _good); } inline ostream& ostream::failif(int cond) { if (cond) set(_fail); return *this; } inline int ostream::is_open() { return bp->is_open(); } inline int ostream::readable() { return 0; } inline int ostream::writable() { return (bp != 0) && (state == _good); } inline char* ostream::bufptr() { return bp->base; } inline ostream& ostream::flush() { bp->overflow(); return *this; } inline ostream& ostream::close() { bp->overflow(); bp->close(); return *this; } inline ostream& ostream::put(char ch) { return failif((state != _good) || bp->sputc(ch) == EOF); } #ifndef NO_OUTPUT_CHAR inline ostream& ostream::operator << (char ch) { return failif((state != _good) || bp->sputc(ch) == EOF); } #endif inline ostream& ostream::put(const char* s) { return failif((state != _good) || bp->sputs(s) == EOF); } inline ostream& ostream::put(const char* s, int len) { return failif((state != _good) || bp->sputsn(s, len) == EOF); } inline ostream& ostream::operator << (const char* s) { return failif((state != _good) || bp->sputs(s) == EOF); } #endif == EOF); } #ifndef NO_OUTPUT_CHAR inline ostream& ostream::operator << (char ch) { return failif((state != _good) || bp->spulibg++/g++-include/istream.h 644 473 0 13350 4677677773 11020 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* *** Version 1.2 -- nearly 100% AT&T 1.2 compatible *** */ /* istream.h now separately includable */ #ifndef _istream_h #pragma once #define _istream_h 1 #include #include class whitespace // a class used only to input and { // discard white space characters char filler; }; class ostream; class istream { friend void eatwhite(istream& s); protected: streambuf* bp; state_value state; // _good/_eof/_fail/_bad ostream* tied_to; char skipws; char ownbuf; void _flush(); char* readline (int chunk_number, char terminator); public: istream(const char* filename, io_mode m, access_mode a, int sk=1, ostream* t = 0); istream(const char* filename, const char* m, int sk=1, ostream* t = 0); istream(int filedesc, io_mode m, int sk=1, ostream* t = 0); istream(FILE* fileptr, int sk=1, ostream* t = 0); istream(int sz, char* buf, int sk=1, ostream* t = 0); istream(int filedesc, int sk=1, ostream* t = 0); istream(int filedesc, char* buf, int buflen, int sk=1, ostream* t = 0); istream(streambuf* s, int sk=1, ostream* t = 0); ~istream(); istream& open(const char* filename, io_mode m, access_mode a); istream& open(const char* filename, const char* m); istream& open(int filedesc, io_mode m); istream& open(FILE* fileptr); istream& open(const char* filenam, open_mode m); istream& close(); ostream* tie(ostream* s); int skip(int); // stream status int rdstate(); int eof(); int fail(); int bad(); int good(); // other status queries int readable(); int writable(); int is_open(); operator void*(); int operator !(); const char* name(); char* bufptr(); // error handling void error(); void clear(state_value f = _good); // poorly named void set(state_value f); // set corresponding bit void unset(state_value f); // clear corresponding bit istream& failif(int cond); // unformatted IO istream& get(char& c); istream& unget(char c); istream& putback(char c); // a synonym for unget istream& get (char* s, int n, char terminator = '\n'); istream& getline(char* s, int n, char terminator = '\n'); istream& gets (char **s, char terminator = '\n'); istream& operator >> (char& c); istream& operator >> (short& n); istream& operator >> (unsigned short& n); istream& operator >> (int& n); istream& operator >> (unsigned int& n); istream& operator >> (long& n); istream& operator >> (unsigned long& n); #ifdef __GNUG__ istream& operator >> (long long& n); istream& operator >> (unsigned long long& n); #endif istream& operator >> (float& n); istream& operator >> (double& n); istream& operator >> (char* s); istream& operator >> (whitespace& w); }; // pre-declared streams extern istream cin; // stdin extern whitespace WS; // for convenience inline void istream::clear(state_value flag) { state = flag; } inline void istream::set(state_value flag) { state = state_value(int(state) | int(flag)); } inline void istream::unset(state_value flag) { state = state_value(int(state) & ~int(flag)); } inline int istream::rdstate() { return int(state); } inline int istream::good() { return state == _good; } inline int istream::eof() { return int(state) & int(_eof); } inline int istream::fail() { return int(state) & int(_fail); } inline int istream::bad() { return int(state) & int(_bad); } inline istream::operator void*() { return (state == _good)? this : 0; } inline int istream::operator !() { return (state != _good); } inline istream& istream::failif(int cond) { if (cond) set(_fail); return *this; } inline int istream::is_open() { return bp->is_open(); } inline int istream::readable() { return (bp != 0) && (bp->is_open()) && (state == _good); } inline int istream::writable() { return 0; } inline char* istream::bufptr() { return bp->base; } inline istream& istream::close() { bp->close(); return *this; } inline int istream::skip(int sk) { int was = skipws; skipws = sk; return was; } inline istream& istream::unget(char c) { if (bp->sputback(c) == EOF) set(_fail); return *this; } inline istream& istream::putback(char c) { if (bp->sputback(c) == EOF) set(_fail); return *this; } inline void eatwhite(istream& s) { s >> WS; } #endif ne int istream::writable() { return 0; } inline char* istream::bufptr() { return bp->base; } inline istream& istream::close() { bp->close(); return *this; } inline int istream::skip(int sk) { int was = skipws; skipws = sk; return was; } inline istream& istream::ulibg++/genclass.sh 644 473 0 4710 4677677773 7321 #!/bin/sh # shell script for generating classes from prototypes # # usage: genclass [-2] type1 {ref, val} [type2 {ref, val}] proto [out-prefix] # search in standard g++ prototype directory & in current PROTODIR=/usr/local/lib/g++-include CURRENTDIR=`pwd` N="1" T2="" T2ACC="" case $1 in -2) N="2"; shift;; *) ;; esac T1=$1; T1NAME=$T1.; T1SEDNAME=$T1; case $2 in ref) T1ACC="\&";; val) T1ACC=" ";; *) echo "Must specify type1 access: ref or val"; exit 1;; esac case $N in 2) T2=$3; T2NAME=$T2.; T2SEDNAME=$T2; case $4 in ref) T2ACC="\&";; val) T2ACC=" ";; *) echo "Must specify type2 access: ref or val"; exit 1;; esac; CLASS=$5;; *) CLASS=$3;; esac REPLACEPREFIX="N" DFLTPREFIX=$T1NAME$T2NAME case $# in 3) PREFIX=$DFLTPREFIX;; 5) PREFIX=$DFLTPREFIX;; 4) PREFIX=$4; REPLACEPREFIX="Y";; 6) PREFIX=$6; REPLACEPREFIX="Y";; *) echo "bad arguments"; exit 1 ;; esac HSRC=$CLASS.hP CCSRC=$CLASS.ccP HOUT=$PREFIX$CLASS.h; CCOUT=$PREFIX$CLASS.cc ; # .h and .cc parts done separately in case only a .h if test -f $CURRENTDIR/$HSRC then HSRC=$CURRENTDIR/$HSRC elif test -f $PROTODIR/$HSRC then HSRC=$PROTODIR/$HSRC else echo "genclass: $HSRC: no such file"; exit 1; fi CASES=$N$REPLACEPREFIX case $CASES in 2Y) sed < $HSRC > $HOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" -e "s/$T1SEDNAME\.$T2SEDNAME\./$PREFIX/g" -e "s/$T1SEDNAME\./$PREFIX/g" -e "s/$T2SEDNAME\./$PREFIX/g" ;; 2N) sed < $HSRC > $HOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" ;; 1Y) sed < $HSRC > $HOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s/$T1SEDNAME\./$PREFIX/g" ;; *) sed < $HSRC > $HOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g";; esac if test -f $CURRENTDIR/$CCSRC then CCSRC=$CURRENTDIR/$CCSRC elif test -f $PROTODIR/$CCSRC then CCSRC=$PROTODIR/$CCSRC else echo "genclass warning: class has a .h but no .cc file"; exit 0; fi case $CASES in 2Y) sed < $CCSRC > $CCOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" -e "s/$T1SEDNAME\.$T2SEDNAME\./$PREFIX/g" -e "s/$T1SEDNAME\./$PREFIX/g" -e "s/$T2SEDNAME\./$PREFIX/g" ;; 2N) sed < $CCSRC > $CCOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" ;; 1Y) sed < $CCSRC > $CCOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s/$T1SEDNAME\./$PREFIX/g" ;; *) sed < $CCSRC > $CCOUT -e "s//$T1/g" -e "s//$T1$T1ACC/g";; esac exit 0sed < $CCSRC > $CCOUT -e "s//$T1/g" -e "s//$T1$T1libg++/libg++.texinfo 644 473 0 511171 4677677776 7676 \input texinfo @c -*-texinfo-*- @settitle User's Guide to the GNU C++ Class Library @setfilename libg++ @ifinfo This file documents the features and implementation of The GNU C++ library Copyright (C) 1988 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 All copyright conditions applying to GNU CC also apply to GNU C++ libraries. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled ``GNU CC General Public License'' is included exactly as in the original, and 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 the section entitled ``GNU CC General Public License'' and this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English. @end ifinfo @iftex @finalout @end iftex @setchapternewpage odd @titlepage @center @titlefont{User's Guide} @sp 2 @center @titlefont{to} @sp 2 @center @titlefont{GNU C++ Library} @sp 4 @center Doug Lea @sp 3 @center last updated 24 February, 1990 @sp 1 @center for version 1.37.0 @page @vskip 0pt plus 1filll Copyright @copyright{} 1988 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 also that the section entitled ``GNU CC General Public License'' is included exactly as in the original, and 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 the section entitled ``GNU CC General Public License'' may be included in a translation approved by the author instead of in the original English. @strong{Note: The GNU C++ library is still in test release. You will be performing a valuable service if you report any bugs you encounter.} @end titlepage @ifinfo @node Top, Copying, , (DIR) Introduction ************ This manual documents how to install and use the GNU C++ library. The GNU C++ library uses the GNU C++ compiler, written by Michael Tiemann and Richard M. Stallman. @end ifinfo @menu * Copying:: GNU CC General Public License says how you can copy and share GNU C++ library. * Contributors:: People who have contributed to GNU C++ library. * Installation:: How to configure, compile and install GNU C++ library * Trouble:: If you have trouble installing GNU C++ library. * General:: Aims, objectives, and limitations of the GNU C++ library * Conventions:: Stylistic conventions * OK:: Support for representation invariants * Proto:: Introduction to container class prototypes * Pix:: Pseudo-indexes * Representations:: How variable-sized objects are represented * Expression:: Some guidance on programming expression-oriented classes * Headers:: Header files and other support for interfacing C++ to C * Builtin:: Utility functions operating on builtin types * New Library dynamic allocation primitives * File:: File-based classes * Stream:: istreams and ostreams * Obstack:: Obstacks and their uses. * AllocRing:: A place to store objects for a while * String:: String, SubString, and Regex classes. * Integer:: Multiple precision Integer class. * Rational:: Multiple precision Rational class * Complex:: Complex number class * Fix:: Fixed point proportion classes * Bit:: BitSet and BitString classes * Random:: Random number generators * Data:: SampleStatistic and related classes for data collection * Curses:: CursesWindow class * List:: Lisp-like List prototype * LinkList:: Singly and doubly linked list class prototypes * Vector:: Vector prototypes * Plex:: Plex (adjustable array) prototypes * Stack:: Stack prototypes * Queue:: Queue prototypes * Deque:: Double ended queue prototypes * PQ:: Heap (priority queue) class prototypes * Set:: Set class prototypes * Bag:: Bag class prototypes * Map:: Map (Associative array) prototypes * GetOpt:: C++ class-based version of the GNU/UNIX getopt function * Gperf:: Perfect Hash Function Generator * Projects:: Things Still Left to do @end menu @node Copying, Contributors, Top, Top @unnumbered GNU CC GENERAL PUBLIC LICENSE @center (Clarified 11 Feb 1988) The license agreements of most software companies keep you at the mercy of those companies. By contrast, our general public license is intended to give everyone the right to share GNU CC. To make sure that you get the rights we want you to have, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. Hence this license agreement. Specifically, we want to make sure that you have the right to give away copies of GNU CC, that you receive source code or else can get it if you want it, that you can change GNU CC or use pieces of it in new free programs, and that you know you can do these things. To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of GNU CC, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. Also, for our own protection, we must make certain that everyone finds out that there is no warranty for GNU CC. If GNU CC is modified by someone else and passed on, we want its recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation. Therefore we (Richard Stallman and the Free Software Foundation, Inc.) make the following terms which say what you must do to be allowed to distribute or change GNU CC. @unnumberedsec COPYING POLICIES @enumerate @item You may copy and distribute verbatim copies of GNU CC source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright notice ``Copyright @copyright{} 1988 Free Software Foundation, Inc.'' (or with whatever year is appropriate); keep intact the notices on all files that refer to this License Agreement and to the absence of any warranty; and give any other recipients of the GNU CC program a copy of this License Agreement along with the program. You may charge a distribution fee for the physical act of transferring a copy. @item You may modify your copy or copies of GNU CC or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: @itemize @bullet @item cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and @item cause the whole of any work that you distribute or publish, that in whole or in part contains or is a derivative of GNU CC or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third parties, at your option). @item You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. @end itemize Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms. @item You may copy and distribute GNU CC (or any portion of it in under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: @itemize @bullet @item accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, @item accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, @item accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) @end itemize For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs. @item You may not copy, sublicense, distribute or transfer GNU CC except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer GNU CC is void and your rights to use the program under this License agreement shall be automatically terminated. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated so long as such parties remain in full compliance. @item If you wish to incorporate parts of GNU CC into other free programs whose distribution conditions are different, write to the Free Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We 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. @end enumerate Your comments and suggestions about our licensing policies and our software are welcome! Please contact the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. @unnumberedsec NO WARRANTY BECAUSE GNU CC IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GNU CC "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 GNU CC IS WITH YOU. SHOULD GNU CC PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE GNU CC AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GNU CC, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. @node Contributors, Installation, Copying, Top @unnumbered Contributors to GNU C++ library Aside from Michael Tiemann, who worked out the front end for GNU C++, and Richard Stallman, who worked out the back end, the following people (not including those who have made their contributions to GNU CC) should not go unmentioned. @itemize @bullet @item Doug Lea contributed most otherwise unattributed classes. @item Dirk Grunwald contributed the Random number generation classes, and PairingHeaps. @item Kurt Baudendistel contributed Fixed precision reals. @item Doug Schmidt contributed ordered hash tables, GPERF, a perfect hash function generator, and several other utilities. @item Marc Shapiro contributed the ideas and preliminary code for Plexes. @item Eric Newton contributed the curses window classes. @end itemize @node Installation, Trouble, Contributors, Top @chapter Installing GNU C++ library @enumerate @item Read through the README file and the Makefile. Make sure that all paths, system-dependent compile switches, and program names are correct. @item Check that files @file{values.h}, @file{stdio.h}, and @file{math.h} declare and define values appropriate for your system. @item Type @samp{make all} to compile the library, test, and install. Current details about contents of the tests and utilities are in the @file{README} file. @end enumerate @node Trouble, General, Installation, Top @chapter Trouble in Installation Here are some of the things that have caused trouble for people installing GNU C++ library. @enumerate @item Make sure that your GNU C++ version number is at least as high as your libg++ version number. For example, libg++ 1.22.0 requires g++ 1.22.0 or later releases. @item Double-check system constants in the header files mentioned above. @end enumerate @node General, Conventions, Trouble, Top @chapter GNU C++ library aims, objectives, and limitations The GNU C++ library, libg++ is an attempt to provide a variety of C++ programming tools and other support to GNU C++ programmers. Differences in distribution policy are only part of the difference between libg++.a and AT&T libC.a. libg++ is not intended to be an exact clone of libC. For one, libg++ contains bits of code that depend on special features of GNU g++ that are either different or lacking in the AT&T version, including slightly different inlining and overloading strategies, dynamic local arrays, wrappers, etc. All of these differences are minor. For example, while the AT&T and GNU stream classes are implemented in very different ways, the vast majority of C++ programs compile and run under either version with no visible difference. libg++ has also contained workarounds for some limitations in g++: both g++ and libg++ are still undergoing rapid development and testing -- a task that is helped tremendously by the feedback of active users. libg++ is not the only freely available source of C++ class libraries. The most notable alternative sources are Interviews and OOPS. (A g++-compatible version of OOPS is currently available on prep.ai.mit.edu. InterViews has been available on the X-windows X11 tapes and also from lurch.stanford.edu. A set of slight modifications needed to make this run with g++ is available on prep.ai.mit.edu.) As every C++ programmer knows, the design (moreso than the implementation) of a C++ class library is something of a challenge. Part of the reason is that C++ supports two, partially incompatible, styles of object-oriented programming -- The "forest" approach, involving a collection of free-standing classes that can be mixed and matched, versus the completely hierarchical (smalltalk style) approach, in which all classes are derived from a common ancestor. Of course, both styles have advantages and disadvantages. So far, libg++ has adopted the "forest" approach. Keith Gorlen's OOPS library adopts the hierarchical approach, and may be an attractive alternative for CC and g++ programmers who prefer this style. Currently (and/or in the near future) libg++ provides support for a few basic kinds of classes: The first kind of support provides an interface between C++ programs and C libraries. This includes basic header files (like @file{stdio.h}) as well as things like the File and stream classes. Other classes that interface to other aspects of C libraries (like those that maintain environmental information) are in various stages of development; all will undergo implementation modifications when the forthcoming GNU libc library is released. The second kind of support contains general-purpose basic classes that transparently manage variable-sized objects on the freestore. This includes Obstacks, multiple-precision Integers and Rationals, arbitrary length Strings, BitSets, and BitStrings. Third, several classes and utilities of common interest (e.g., Complex numbers) are provided. Fourth, a set of pseudo-generic prototype files are available as a mechanism for generating common container classes. These are described in more detail in the introduction to container prototypes. Currently, only a the textual substitution mechanism is available for generic class creation. @node Conventions, OK, General, Top @chapter GNU C++ library stylistic conventions @itemize @bullet @item C++ source files have file extension @file{.cc}. Both C-compatibility header files and class declaration files have extension @file{.h}. @item C++ class names begin with capital letters, except for @code{istream} and @code{ostream}, for AT&T C++ compatibility. Multi-word class names capitalize each word, with no underscore separation. @item Include files that define C++ classes begin with capital letters (as do the names of the classes themselves). @file{stream.h} is uncapitalized for AT&T C++ compatibility. @item Include files that supply function prototypes for other C functions (system calls and libraries) are all lower case. @item All include files define a preprocessor variable _X_h, where X is the name of the file, and conditionally compile only if this has not been already defined. The @code{#pragma once} facility is also used to avoid re-inclusion. @item Structures and objects that must be publicly defined, but are not intended for public use have names beginning with an underscore. (for example, the @code{_Srep} struct, which is used only by the String and SubString classes.) @item The underscore is used to separate components of long function names, @*e.g., @code{set_File_exception_handler()}. @item When a function could be usefully defined either as a member or a friend, it is generally a member if it modifies and/or returns itself, else it is a friend. There are cases where naturalness of expression wins out over this rule. @item Class declaration files are formatted so that it is easy to quickly check them to determine function names, parameters, and so on. Because of the different kinds of things that may appear in class declarations, there is no perfect way to do this. Any suggestions on developing a common class declaration formatting style are welcome. @item All classes use the same simple error (exception) handling strategy. Almost every class has a member function named @code{error(char* msg)} that invokes an associated error handler function via a pointer to that function, so that the error handling function may be reset by programmers. By default nearly all call @code{*lib_error_handler}, which prints the message and then aborts execution. This system is subject to change. In general, errors are assumed to be non-recoverable: Library classes do not include code that allows graceful continuation after exceptions. @end itemize @node OK, Proto, Conventions, Top @chapter Support for representation invariants Most GNU C++ library classes possess a method named @code{OK()}, that is useful in helping to verify correct performance of class operations. The @code{OK()} operations checks the ``representation invariant'' of a class object. This is a test to check whether the object is in a valid state. In effect, it is a verification of the library's promise that (1) class operations always leave objects in valid states, and (2) the class protects itself so that client functions cannot corrupt this state. While no simple validation technique can assure that all operations perform correctly, calls to @code{OK()} can at least verify that operations do not corrupt representations. For example for @code{String a, b, c; ... a = b + c;}, a call to @code{a.OK();} will guarantee that @code{a} is a valid @code{String}, but does not guarantee that it contains the concatenation of @code{b + c}. However, given that @code{a} is known to be valid, it is possible to further verify its properties, for example via @code{a.after(b) == c && a.before(c) == b}. In other words, @code{OK()} generally checks only those internal representation properties that are otherwise inaccessible to users of the class. Other class operations are often useful for further validation. Failed calls to @code{OK()} call a class's @code{error} method if one exists, else the directly call @code{abort}. Failure indicates an implementation error that should be reported. With only rare exceptions, the internal support functions for a class never themselves call @code{OK()} (although many of the test files in the distribution call @code{OK()} extensively). Verification of representational invariants can sometimes be very time consuming for complicated data structures. @node Proto, Pix, OK, Top @chapter Introduction to container class prototypes As a temporary mechanism enabling the support of generic classes, the GNU C++ Library distribution contains a directory (@file{g++-include}) of files designed to serve as the basis for generating container classes of specified elements. These files can be used to generate @file{.h} and @file{.cc} files in the current directory via a supplied shell script program that performs simple textual substitution to create specific classes. While these classes are generated independently, and thus share no code, it is possible to create versions that do share code among subclasses. For example, using @code{typedef void* ent}, and then generating a @code{entList} class, other derived classes could be created using the @code{void*} coercion method described in Stroustrup, pp204-210. This very simple class-generation facility is useful enough to serve current purposes, but will be replaced with a more coherent mechanism for handling C++ generics in a way that minimally disrupts current usage. Without knowing exactly when or how parametric classes might be added to the C++ language, provision of this simplest possible mechanism, textual substitution, appears to be the safest strategy, although it does require certain redundancies and awkward constructions. Specific classes may be generated via the @file{genclass} shell script program. This program has arguments specifying the kinds of base types(s) to be used. Specifying base types requires two arguments. The first is the name of the base type, which may be any named type, like @code{int} or @code{String}. Only named types are supported; things like @code{int*} are not accepted. However, pointers like this may be used by supplying the appropriate typedefs (e.g., editing the resulting files to include @code{typedef int* intp;}). The type name must be followed by one of the words @code{val} or @code{ref}, to indicate whether the base elements should be passed to functions by-value or by-reference. Basic container classes may be specified via @code{genclass base [val,ref] proto}, where @code{proto} is the name of the class being generated. Container classes like dictionaries and maps that require two types may be specified via @code{genclass -2 keytype [val, ref], basetype [val, ref] proto}, where the key type is specified first and the contents type second. The resulting classnames and filenames are generated by prepending the specified type names to the prototype names, and separating the filename parts with dots. For example, @code{genclass int val List} generates class @code{intList} residing in files @file{int.List.h} and @file{int.List.cc}. @code{genclass -2 String ref int val VHMap} generates (the awkward, but unavoidable) class name @code{StringintVHMap}. Of course, programmers may use @code{typedef} or simple editing to create more appropriate names. The existence of dot seperators in file names allows the use of GNU make to help automate configuration and recompilation. An example Makefile exploiting such capabilities may be found in the @file{libg++/proto-kit} directory. The @code{genclass} utility operates via simple text substitution using @code{sed}. All occurrences of the pseudo-types @code{} and @code{} (if there are two types) are replaced with the indicated type, and occurrences of @code{} and @code{} are replaced by just the types, if @code{val} is specified, or types followed by ``&'' if @code{ref} is specified. Programmers will frequently need to edit the @file{.h} file in order to insert additional @code{#include} directives or other modifications. A simple utility, @file{prepend-header} to prepend other @file{.h} files to generated files is provided in the distribution. One dubious virtue of the prototyping mechanism is that, because sources files, not archived library classes, are generated, it is relatively simple for programmers to modify container classes in the common case where slight variations of standard container classes are required. It is often a good idea for programmers to archive (via @code{ar}) generated classes into @file{.a} files so that only those class functions actually used in a given application will be loaded. The test subdirectory of the distribution shows an example of this. Many container classes require specifications over and above the base class type. For example, classes that maintain some kind of ordering of elements require specification of a comparison function upon which to base the ordering. This is accomplished via a prototype file @file{defs.hP} that contains macros for these functions. While these macros default to perform reasonable actions, they can and should be changed in particular cases. Most prototypes require only one or a few of these. No harm is done if unused macros are defined to perform nonsensical actions. The macros are: @table @code @item DEFAULT_INITIAL_CAPACITY The intitial capacity for containers (e.g., hash tables) that require an initial capacity argument for constructors. Default: 100 @item EQ(a, b) return true if a is considered equal to b for the purposes of locating, etc., an element in a container. Default: (a == b) @item LE(a, b) return true if a is less than or equal to b Default: (a <= b) @item CMP(a, b) return an integer < 0 if a 0 if a>b. Default: (a <= b)? (a==b)? 0 : -1 : 1 @item HASH(a) return an unsigned integer representing the hash of a. Default: hash(a) ; where extern unsigned int hash(). (note: several useful hash functions are declared in builtin.h and defined in hash.cc) @end table Nearly all prototypes container classes support container traversal via @code{Pix} pseudo indices, as described elsewhere. @node Representations, Expressions, Proto, Top @chapter How variable-sized objects are represented. One of the first goals of the GNU C++ library is to enrich the kinds of basic classes that may be considered as (nearly) ``built into'' C++. A good deal of the inspiration for these efforts is derived from considering features of other type-rich languages, particularly Common Lisp and Scheme. The general characteristics of most class and friend operators and functions supported by these classes has been heavily influenced by such languages. Four of these types, Strings, Integers, BitSets, and BitStrings (as well as associated and/or derived classes) require representations suitable for managing variable-sized objects on the free-store. The basic technique used for all of these is the same, although various details necessarily differ from class to class. The general strategy for representing such objects is to create chunks of memory that include both header information (e.g., the size of the object), as well as the variable-size data (an array of some sort) at the end of the chunk. Generally the maximum size of an object is limited to something less than all of addressable memory, as a safeguard. The minimum size is also limited so as not to waste allocations expanding very small chunks. Internally, chunks are allocated in blocks well-tuned to the performance of the @code{new} operator. Class elements themselves are merely pointers to these chunks. Most class operations are performed via inline ``translation'' functions that perform the required operation on the corresponding representation. However, constructors and assignments operate by copying entire representations, not just pointers. No attempt is made to control temporary creation in expressions and functions involving these classes. Users of previous versions of the classes will note the disappearance of both ``Tmp'' classes and reference counting. These were dropped because, while they did improve performance in some cases, they obscure class mechanics, lead programmers into the false belief that they need not worry about such things, and occaisionally have paradoxical behavior. These variable-sized object classes are integrated as well as possible into C++. Most such classes possess converters that allow automatic coercion both from and to builtin basic types. (e.g., char* to and from String, long int to and from Integer, etc.). There are pro's and con's to circular converters, since they can sometimes lead to the conversion from a builtin type through to a class function and back to a builtin type without any special attention on the part of the programmer, both for better and worse. Most of these classes also provide special-case operators and functions mixing basic with class types, as a way to avoid constructors in cases where the operations do not rely on anything special about the representations. For example, there is a special case concatenation operator for a String concatenated with a char, since building the result does not rely on anything about the String header. Again, there are arguments both for and against this approach. Supporting these cases adds a non-trivial degree of (mainly inline) function proliferation, but results in more efficient operations. Efficiency wins out over parsimony here, as part of the goal to produce classes that provide sufficient functionality and efficiency so that programmers are not tempted to try to manipulate or bypass the underlying representations. @node Expressions, Pix, Representations, Top @chapter Some guidelines for using expression-oriented classes The fact that C++ allows operators to be overloaded for user-defined classes can make programming with library classes like @code{Integer}, @code{String}, and so on very convenient. However, it is worth becoming familiar with some of the inherent limitations and problems associated with such operators. Many operators are @emph{constructive}, i.e., create a new object based on some function of some arguments. Sometimes the creation of such objects is wasteful. Most library classes supporting expressions contain facilities that help you avoid such waste. For example, for @code{Integer a, b, c; ...; c = a + b + a;}, the plus operator is called to sum a and b, creating a new temporary object as its result. This temporary is then added with a, creating another temporary, which is finally copied into c, and the temporaries are then deleted. For small objects, simple operators, and/or non-time/space critical programs, creation of temporaries is not a big problem. However, often, when fine-tuning a program, it may be a good idea to rewrite such code in a less pleasant, but more efficient manner. For builtin types like ints, and floats, C and C++ compilers already know how to optimize such expressions to reduce the need for temporaries. Unfortunately, this is not true for C++ user defined types, for the simple (but very annoying, in this context) reason that nothing at all is guaranteed about the semantics of overloaded operators and their interrelations. For example, if the above expression just involved ints, not Integers, a compiler might internally convert the statement into something like @code{ c += a; c += b; c+= a; }, or perhaps something even more clever. But since C++ does not know that Integer operator += has any relation to Integer operator +, A C++ compiler cannot do this kind of expression optimization itself. In many cases, you can avoid construction of temporaries simply by using the assignment versions of operators whenever possible, since these versions create no temporaries. However, for maximum flexibility, most classes provide a set of ``embedded assembly code'' procedures that you can use to fully control time, space, and evaluation strategies. Most of these procedures are ``three-address'' procedures that take two @code{const} source arguments, and a destination argument. The procedures perform the appropriate actions, placing the results in the destination (which is may involve overwriting old contents). These procedures are designed to be fast and robust. In particular, aliasing is always handled correctly, so that, for example @code{add(x, x, x); } is perfectly OK. (The names of these procedures are listed along with the classes.) For example, suppose you had an Integer expression @code{ a = (b - a) * -(d / c); } This would be compiled as if it were @code{ Integer t1=b-a; Integer t2=d/c; Integer t3=-t2; Integer t4=t1*t3; a=t4;} But, with some manual cleverness, you might yourself some up with @code{ sub(a, b, a); mul(a, d, a); div(a, c, a); } A related phenomenon occurs when creating your own constructive functions returning instances of such types. Suppose you wanted to write function @code{Integer f(const Integer& a) @{ Integer r = a; r += a; return r; @}} This function, when called (as in @code{ a = f(a); }) demonstrates a similar kind of wasted copy. The returned value r must be copied out of the function before it can be used by the caller. In GNU C++, there is an alternative via the use of named return values. Named return values allow you to manipulate the returned object directly, rather than requiring you to create a local inside a function and then copy it out as the returned value. In this example, this can be done via @code{Integer f(const Integer& a) return r(a) @{ r += a; return; @}} A final guideline: The overloaded operators are very convenient, and much clearer to use than procedural code. It is almost always a good idea to make it right, @emph{then} make it fast, by translating expression code into procedural code after it is known to be correct. @node Pix, Headers, Proto, Top @chapter Pseudo-indexes Many useful classes operate as containers of elements. Techniques for accessing these elements from a container differ from class to class. In the GNU C++ library, access methods have been partially standardized across different classes via the use of pseudo-indexes called @code{Pixes}. A @code{Pix} acts in some ways like an index, and in some ways like a pointer. (Their underlying representations are just @code{void*} pointers). A @code{Pix} is a kind of ``key'' that is translated into an element access by the class. In virtually all cases, @code{Pixes} are pointers to some kind internal storage cells. The containers use these pointers to extract items. @code{Pixes} support traversal and inspection of elements in a collection using analogs of array indexing. However, they are pointer-like in that @code{0} is treated as an invalid @code{Pix}, and unsafe insofar as programmers can attempt to access nonexistent elements via dangling or otherwise invalid @code{Pixes} without first checking for their validity. In general it is a very bad idea to perform traversals in the the midst of destructive modifications to containers. Typical applications might include code using the idiom @example for (Pix i = a.first(); i != 0; a.next(i)) use(a(i)); @end example for some container @code{a} and function @code{use}. Classes supporting the use of @code{Pixes} always contain the following methods, assuming a container @code{a} of element types of @code{Base}. @table @code @item Pix i = a.first() Set i to index the first element of a or 0 if a is empty. @item a.next(i) advance i to the next element of a or 0 if there is no next element; @item Base x = a(i); a(i) = x; a(i) returns a reference to the element indexed by i. @item int present = a.owns(i) returns true if Pix i is a valid Pix in a. This is often a relatively slow operation, since the collection must usually traverse through elements to see if any correspond to the Pix. @end table Some container classes also support backwards traversal via @table @code @item Pix i = a.last() Set i to the last element of a or 0 if a is empty. @item a.prev(i) sets i to the previous element in a, or 0 if there is none. @end table Collections supporting elements with an equality operation possess @table @code @item Pix j = a.seek(x) sets j to the index of the first occurrence of x, or 0 if x is not contained in a. @end table Bag classes possess @table @code @item Pix j = a.seek(x, Pix from = 0) sets j to the index of the next occurrence of x following i, or 0 if x is not contained in a. If i == 0, the first occurrence is returned. @end table Set, Bag, and PQ classes possess @table @code @item Pix j = a.add(x) (or a.enq(x) for priority queues) add x to the collection, returning its Pix. The Pix of an item can change in collections where further additions and deletions involve the actual movement of elements (currently in OXPSet, OXPBag, XPPQ, VOHSet), but in all other cases, an item's Pix may be considered a permanent key to its location. @end table @node Headers, Builtin, Representations, Top @chapter Header files and support for interfacing C++ to C The following files are provided so that C++ programmers may invoke common C library and system calls. The names and contents of these files are subject to change in order to be compatible with the forthcoming GNU C library. @table @samp @item values.h A collection of constants defining the numbers of bits in builtin types, minimum and maximum values, and the like. Most names are the same as those found in @file{values.h} found on Sun systems. @item std.h A collection of common system calls and @file{libc.a} functions. Only those functions that can be declared without introducing new type definitions (socket structures, for example) are provided. Common @code{char*} functions (like @code{strcmp}) are among the declarations. All functions are declared along with their library names, so that they may be safely overloaded. @item string.h This file merely includes @file{}, where string function prototypes are declared. This is a workaround for the fact that system @file{string.h} and @file{strings.h} files often differ in contents. @item osfcn.h This file merely includes @file{}, where system function prototypes are declared. @item libc.h This file merely includes @file{}, where C library function prototypes are declared. @item math.h A collection of prototypes for functions usually found in libm.a, plus some @code{#define}d constants that appear to be consistent with those provided in the AT&T version. The value of @code{HUGE} should be checked before using. Declarations of all common math functions are preceded with @code{overload} declarations, since these are commonly overloaded. @item stdio.h Declaration of @code{FILE} (@code{_iobuf}), common macros (like @code{getc}), and function prototypes for @file{libc.a} functions that operate on @code{FILE*}'s. The value @code{BUFSIZ} and the declaration of @code{_iobuf} should be checked before using. @item stddef.h ANSI-based @code{#define}'s. @item stdarg.h Definitions for vararg declarations. This is the version provided with the GNU CC distribution. @item assert.h C++ versions of assert macros. @item generic.h String concatenation macros useful in creating generic classes. They are similar in function to the AT&T CC versions. @end table @node Builtin, New, Headers, Top @chapter Utility functions operating on built in types. Files @file{builtin.h} and corresponding @file{.cc} implementation files contain various convenient inline and non-inline utility functions. These include useful enumeration types, such as @code{TRUE}, @code{FALSE} ,the type definition for pointers to libg++ error handling functions, and the following functions. @table @code @item long abs(long x); double abs(double x); inline versions of abs. Note that the standard libc.a version, @code{int abs(int)} is @emph{not} declared as inline. @item void clearbit(long& x, long b); clears the b'th bit of x (inline). @item void setbit(long& x, long b); sets the b'th bit of x (inline) @item int testbit(long x, long b); returns the b'th bit of x (inline). @item int even(long y); returns true if x is even (inline). @item int odd(long y); returns true is x is odd (inline). @item int sign(long x); int sign(double x); returns -1, 0, or 1, indicating whether x is less than, equal to, or greater than zero (inline). @item long gcd(long x, long y); returns the greatest common divisor of x and y. @item long lcm(long x, long y); returns the least common multiple of x and y. @item long lg(long x); returns the floor of the base 2 log of x. @item long pow(long x, long y); double pow(double x, long y); returns x to the integer power y using via the iterative O(log y) ``Russian peasant'' method. @item long sqr(long x); double sqr(double x); returns x squared (inline). @item long sqrt(long y); returns the floor of the square root of x. @item unsigned int hashpjw(const char* s); a hash function for null-terminated char* strings using the method described in Aho, Sethi, & Ullman, p 436. @item unsigned int multiplicativehash(int x); a hash function for integers that returns the lower bits of multiplying x by the golden ratio times pow(2, 32). See Knuth, Vol 3, p 508. @item unsigned int foldhash(double x); a hash function for doubles that exclusive-or's the first and second words of x, returning the result as an integer. @item double start_timer() Starts a process timer. @item double return_elapsed_time(double last_time) Returns the process time since last_time. If last_time == 0 returns the time since the last start_timer. Returns -1 if start_timer was not first called. @end table The following conversion functions are also provided. Functions that convert objects to char* strings return pointers to a space that is reused upon each call. Thus the results are valid only until the next call to a conversion function. @table @code @item char* itoa(long x, int base = 10, int width = 0); returns a char* string containing the ASCII representation of x in the specified base. If the representation fits in space less than width, blanks are prepended. @item char* dtoa(double x, char cvt='g', int width=0, int prec=6) returns a char* string containing the ASCII representation of x converted in a printf-like manner, where the optional arguments correspond to those in printf g, f, and e formats. For example, the analog of @code{printf("%f10.2", x)} is @code{dtoa(x, 'f', 10, 2)}. @item char* hex(long x, int width = 0); returns itoa using base 16. @item char* oct(long x, int width = 0); returns itoa using base 8. @item char* dec(long x, int width = 0); returns itoa using base 10. @item char* form(const char* fmt ...); calls @code{sprintf} with the given format and arguments. @item char* chr(char ch); returns ch as a one-element string. @end table @node New, File, Builtin, Top @chapter Library dynamic allocation primitives Libg++ contains versions of @code{malloc, free, realloc} that were designed to be well-tuned to C++ applications. The source file @file{malloc.c} contains some design and implementation details. Here are the major user-visible differences from most system malloc routines: @enumerate @item These routines @emph{overwrite} storage of freed space. This means that it is never permissible to use a @code{delete}'d object in any way. Doing so will either result in trapped fatal errors or random aborts within malloc, free, or realloc. @item The routines tend to perform well when a large number of objects of the same size are allocated and freed. You may find that it is not worth it to create your own special allocation schemes in such cases. @item The library sets top-level @code{operator new()} to call malloc and @code{operator delete()} to call free. Of course, you may override these definitions in C++ programs by creating your own operators that will take precedence over the library versions. However, if you do so, be sure to define @emph{both} @code{operator new()} and @code{operator delete()}. @item These routines do @emph{not} support the odd convention, maintained by some versions of malloc, that you may call @code{realloc} with a pointer that has been @code{free}'d. @item The routines automatically perform simple checks on @code{free}'d pointers that can often determine whether users have accidentally written beyond the boundaries of allocated space, resulting in a fatal error. @item The function @code{malloc_usable_size(void* p)} returns the number of bytes actually allocated for @code{p}. For a valid pointer (i.e., one that has been @code{malloc}'d or @code{realloc}'d but not yet @code{free}'d) this will return a number greater than or equal to the requested size, else it will normally return 0. Unfortunately, a non-zero return can not be an absolutely perfect indication of lack of error. If a chunk has been @code{free}'d but then re-allocated for a different purpose somewhere elsewhere, then @code{malloc_usable_size} will return non-zero. Despite this, the function can be very valuable for performing run-time consistency checks. @item @code{malloc} requires 8 bytes of overhead per allocated chunk, plus a mmaximum alignment adjustment of 8 bytes. The number of bytes of usable space is exactly as requested, rounded to the nearest 8 byte boundary. @item The routines do @emph{not} contain any synchronization support for multiprocessing. If you perform global allocation on a shared memory multiprocessor, you should disable compilation and use of libg++ malloc in the distribution @file{Makefile} and use your system version of malloc. @end enumerate @node File, Stream, New, Top @chapter File-based classes The @code{File} class supports basic IO on Unix files. Operations are based on common C stdio library functions. @code{File} serves as the base class for istreams, ostreams, and other derived classes. It contains the interface between the Unix stdio file library and these more structured classes. Most operations are implemented as simple calls to stdio functions. @code{File} class operations are also fully compatible with raw system file reads and writes (like the system @code{read} and @code{lseek} calls) when buffering is disabled (see below). The @code{FILE*} stdio file pointer is, however maintained as protected. Classes derived from File may only use the IO operations provided by File, which encompass essentially all stdio capabilities. The class contains four general kinds of functions: methods for binding @code{File}s to physical Unix files, basic IO methods, file and buffer control methods, and methods for maintaining logical and physical file status. @section Binding Binding and related tasks are accomplished via @code{File} constructors and destructors, and member functions @code{open, close, remove, filedesc, name, setname}. @code{Files} may be constructed in any of the ways supported by a version of @code{open}, plus a default constructor. They differ in specifying if @itemize @bullet @item a file with a given filename should be opened. The second argument refers to the IO mode, which may be any of @table @code @item io_readonly open the file for reading only. Attempted writes cause @code{_fail} status. @item io_writeonly open the file for writing only. Attempted reads cause @code{_fail} status. @item io_readwrite open the file for reading and/or writing. @item io_appendonly open the file for appending (writing at end) only. @end table The third represents the access mode: @table @code @item a_createonly create the file, fail if it already exists. @item a_create create the file, re-create (truncate) if it already exists. @item a_useonly open an existing file, fail if it does not exist. @item a_use open an existing file, create if it does not exist. @end table @item same as above, except the mode is given using the @code{fopen} char* string argument (@code{"r", "w", "a", "r+", "w+", "a+"}). @item the @code{File} should be bound to a file associated with the given (open) file descriptor. This method should be used only if a file pointer associated with the file descriptor has not yet been obtained. The second argument specifies the io_mode, as above. This must match the actual IO mode of the file. @item the @code{File} should be bound to a FILE* file pointer already somehow obtained. This is mainly used to bind @code{Files} to the default stdin, stdout, and stderr files. @item the @code{File} should not yet be bound to anything. Files may be declared via this default, and then later opened via @code{open}. @item the @code{File} should perform IO into or out of a user supplied character buffer with an indicated size, instead of to an actual file. @end itemize After a successful open, the corresponding file descriptor is accessible (for use in system calls, etc.) via @code{filedesc()}. A @code{File} may be bound to different physical files at different times: each call to @code{open}, closes the old physical file and rebinds the @code{File} to a new physical file. If a file name is provided in a constructor or open, it is maintained as class variable @code{nm} and is accessible via @code{name}. If no name is provided, then @code{nm} remains null, except that @code{Files} bound to the default files stdin, stdout, and stderr are automatically given the names @code{(stdin), (stdout), (stderr)} respectively. The function @code{setname} may be used to change the internal name of the @code{File}. This does not change the name of the physical file bound to the File. The member function @code{close} closes a file. The @code{~File} destructor closes a file if it is open, except that stdin, stdout, and stderr are flushed but left open for the system to close on program exit since some systems may require this, and on others it does not matter. @code{remove} closes the file, and then deletes it if possible by calling the system function to delete the file with the name provided in the @code{nm} field. @section Basic IO @itemize @bullet @item @code{read} and @code{write} perform binary IO via stdio @code{fread} and @code{fwrite}. @item @code{get} and @code{put} for chars invoke stdio @code{getc} and @code{putc} macros. @item @code{get(char* s, int maxlength, char terminator='\n')} behaves as described by Stroustrup. It reads at most maxlength characters into s, stopping when the terminator is read, and pushing the terminator back into the input stream. To accommodate different conventions about what to do about the terminator, the function @code{getline(char* s, int maxlength, char terminator='\n')} behaves like get, except that the terminator becomes part of the string, and is not pushed back. @refill @item @code{gets(char **sp, char terminator = '\n');} like get, except sp is attached to a char* allocated from the freestore, and containing the line read in. @item @code{put(const char* s)} outputs a null-terminated string via stdio @code{fputs}. @item @code{unget} and @code{putback} are synonyms. Both call stdio @code{ungetc}. @end itemize @section File Control @code{flush}, @code{seek}, @code{tell}, and @code{tell} call the corresponding stdio functions. @code{flush(char)} and @code{fill()} call stdio @code{_flsbuf} and @code{_filbuf} respectively. @code{setbuf} is mainly useful to turn off buffering in cases where nonsequential binary IO is being performed. @code{raw} is a synonym for @code{setbuf(_IONBF)}. After a @code{f.raw()}, using the stdio functions instead of the system @code{read, write}, etc., calls entails very little overhead. Moreover, these become fully compatible with intermixed system calls (e.g., @code{lseek(f.filedesc(), 0, 0)}). While intermixing @code{File} and system IO calls is not at all recommended, this technique does allow the @code{File} class to be used in conjunction with other functions and libraries already set up to operate on file descriptors. @code{setbuf} should be called at most once after a constructor or open, but before any IO. @section File Status File status is maintained in several ways. A @code{File} may be checked for accessibility via @code{is_open()}, which returns true if the File is bound to a usable physical file, @code{readable()}, which returns true if the File can be read from (opened for reading, and not in a _fail state), or @code{writable()}, which returns true if the File can be written to. @code{File} operations return their status via two means: failure and success are represented via the logical state. Also, the return values of invoked stdio and system functions that return useful numeric values (not just failure/success flags) are held in a class variable accessible via @code{iocount}. (This is useful, for example, in determining the number of items actually read by the @code{read} function.) Like the AT&T i/o-stream classes, but unlike the description in the Stroustrup book, p238, @code{rdstate()} returns the bitwise OR of @code{_eof}, @code{_fail} and @code{_bad}, not necessarily distinct values. The functions @code{eof()}, @code{fail()}, @code{bad()}, and @code{good()} can be used to test for each of these conditions independently. @code{_fail} becomes set for any input operation that could not read in the desired data, and for other failed operations. As with all Unix IO, @code{_eof} becomes true only when an input operations fails because of an end of file. Therefore, @code{_eof} is not immediately true after the last successful read of a file, but only after one final read attempt. Thus, for input operations, @code{_fail} and @code{_eof} almost always become true at the same time. @code{bad} is set for unbound files, and may also be set by applications in order to communicate input corruption. Conversely, @code{_good} is defined as 0 and is returned by @code{rdstate()} if all is well. The state may be modified via @code{clear(flag)}, which, despite its name, sets the corresponding state_value flag. @code{clear()} with no arguments resets the state to @code{_good}. @code{failif(int cond)} sets the state to @code{_fail} only if @code{cond} is true. Errors occuring during constructors and file opens also invoke the function @code{error}. @code{error} in turn calls a resetable error handling function pointed to by the non-member global variable @code{File_error_handler} only if a system error has been generated. Since @code{error} cannot tell if the current system error is actually responsible for a failure, it may at times print out spurious messages. Three error handlers are provided. The default, @code{verbose_File_error_handler} calls the system function @code{perror} to print the corresponding error message on standard error, and then returns to the caller. @code{quiet_File_error_handler} does nothing, and simply returns. @code{fatal_File_error_handler} prints the error and then aborts execution. These three handlers, or any other user-defined error handlers can be selected via the non-member function @code{set_File_error_handler}. All read and write operations communicate either logical or physical failure by setting the @code{_fail} flag. All further operations are blocked if the state is in a @code{_fail} or@code{_bad} condition. Programmers must explicitly use @code{clear()} to reset the state in order to continue IO processing after either a logical or physical failure. C programmers who are unfamiliar with these conventions should note that, unlike the stdio library, @code{File} functions indicate IO success, status, or failure solely through the state, not via return values of the functions. The @code{void*} operator or @code{rdstate()} may be used to test success. In particular, according to c++ conversion rules, the @code{void*} coercion is automatically applied whenever the @code{File&} return value of any @code{File} function is tested in an @code{if} or @code{while}. Thus, for example, an easy way to copy all of stdin to stdout until eof (at which point @code{get} fails) or some error is @code{char c; while(cin.get(c) && cout.put(c));}. @section The SFile class @code{SFile} (short for structure file) is provided both as a demonstration of how to build derived classes from @code{File}, and as a useful class for processing files containing fixed-record-length binary data. They are created with constructors with one additional argument declaring the size (in bytes, i.e., @code{sizeof} units) of the records. @code{get}, will input one record, @code{put} will output one, and the @code{[]} operator, as in @code{f[i]}, will position to the i'th record. If the file is being used mainly for random access, it is often a good idea to eliminate internal buffering via @code{setbuf} or @code{raw}. Here is an example: @example class record @{ friend class SFile; char c; int i; double d; // or anything at all @}; void demo() @{ record r; SFile recfile("mydatafile", sizeof(record), io_readwrite, a_create); recfile.raw(); for (int i = 0; i < 10; ++i) // ... write some out @{ r = something(); recfile.put(&r); // must use '&r' for proper coercion @} for (i = 9; i >= 0; --i) // now use them in reverse order @{ recfile[i].get(&r); do_something_with(r); @} @} @end example @section The PlotFile Class Class @code{PlotFile} is a simple derived class of @code{File} that may be used to produce files in Unix plot format. Public functions have names corresponding to those in the @code{plot(5)} manual entry. @node Stream, Obstack, File, Top @chapter The istream and ostream classes The stream class provides an efficient, easy-to-use, and type-secure interface between GNU C++ and an underlying input/output facility, such as the one provided by UNIX. This section documents the implementation highlights of the GNU C++ stream facility. For a more complete discussion about what streams provide and how they are used, see Stroustrup's ``The C++ Programming Language.'' Classes @code{istream} and @code{ostream} are implemented similarly to those described by Stroustrup. All programs using the AT&T stream classes should run without modification, except for one minor difference: @code{f << c} behaves like @code{f.put(c)}. This feature (which is also present in AT&T 2.0) may be disabled by placing @code{#define NO_OUTPUT_CHAR} before including @file{stream.h}. The stream and streambuf classes are actually supersets of the AT&T versions. The major addition is support for files accessed via the libg++ @code{File} classes. Any istream or ostream declared using the constructors and/or open statements corresponding to those available for @code{File} creates a @code{Filebuf} (a derived class of @code{streambuf}), with generally more powerful capabilities than those for AT&T @code{filebufs} (which are also supported). Beyond those contained in AT&T streams, and the extra @code{Filebuf} constructors and open methods, the following capabilities are supported: @table @code @item istream::is_open(); ostream::is_open() returns true if the underlying streambuf is attached to a usable file and/or buffer. @item istream::close(); ostream::close() closes any file and/or buffer associated with the stream. @item istream::readable(); ostream::writable() returns true if the stream is open and in a ``good'' state. @item istream::getline(char* s, int n, char terminator = '\n'); As in File::getline() @item istream::gets(char** ss, char terminator = '\n') reads in a line (as in get) of unknown length, and places it in a free-store allocated spot and attaches it to @code{ss}. The programmer must take responsibility for deleting @code{*ss} when it is no longer needed. @item istream::name(); ostream::name() returns a name associated with the streambuf, if one exists. Currently only streams based on @code{File/Filebuf} possess names. @item istream::error(); ostream::error() calls the streambuf's error handler. Error handlers for @code{File} based streams are resettable. The default streambuf error handler just calls @code{abort()}. @item ostream::put(const char* s, int len) outputs the first len characters of s. @item ostream::form(const char* format...) outputs @code{printf}-formated data. @end table Some of these are supported by incorporating additional, mainly virtual, functions into streambufs: @table @code @item streambuf::open([various args]) attaches the streambuf to a file, if applicable @item streambuf::close() detaches the streambuf from a file, if applicable. @item streambuf::sputs(const char* s) outputs null-terminated string s in a generally faster way than repeated @code{sputcs}. @item streambuf::sputsn(const char* s, int n) outputs the first n characters of s in a generally faster way than repeated @code{sputcs}. @item streambuf::error() By default, calls @code{abort}. @end table The current version of istreams and ostreams differs significantly from previous versions in order to obtain compatibility with AT&T 1.2 streams. Most code using previous versions should still work. However, the following features of @code{File} are not incorporated in streams (they are still present in @code{File}): @code{scan(const char* fmt...), remove(), read(), write(), setbuf(), raw()}. Additionally, the feature of previous streams that allowed free intermixing of stream and stdio input and output is no longer guaranteed to always behave as desired. @node Obstack, AllocRing, Stream, Top @chapter The Obstack class The @code{Obstack} class is a simple rewrite of the C obstack macros and functions provided in the GNU CC compiler source distribution. Obstacks provide a simple method of creating and maintaining a string table, optimized for the very frequent task of building strings character-by-character, and sometimes keeping them, and sometimes not. They seem especially useful in any parsing application. One of the test files demonstrates usage. A brief summary: @table @code @item grow places something on the obstack without committing to wrap it up as a single entity yet. @item finish wraps up a constructed object as a single entity, and returns the pointer to its start address. @item copy places things on the obstack, and @emph{does} wrap them up. @code{copy} is always equivalent to first grow, then finish. @item free deletes something, and anything else put on the obstack since its creation. @end table The other functions are less commonly needed: @table @code @item blank is like grow, except it just grows the space by size units without placing anything into this space @item alloc is like @code{blank}, but it wraps up the object and returns its starting address. @item chunk_size, base, next_free, alignment_mask, size, room returns the appropriate class variables. @item grow_fast places a character on the obstack without checking if there is enough room. @item blank_fast like @code{blank}, but without checking if there is enough room. @item shrink(int n) shrink the current chunk by n bytes. @item contains(void* addr) returns true if the Obstack holds the address addr. @end table Here is a lightly edited version of the original C documentation: These functions operate a stack of objects. Each object starts life small, and may grow to maturity. (Consider building a word syllable by syllable.) An object can move while it is growing. Once it has been ``finished'' it never changes address again. So the ``top of the stack'' is typically an immature growing object, while the rest of the stack is of mature, fixed size and fixed address objects. These routines grab large chunks of memory, using the GNU C++ @code{new} operator. On occasion, they free chunks, via @code{delete}. Each independent stack is represented by a Obstack. One motivation for this package is the problem of growing char strings in symbol tables. Unless you are a ``fascist pig with a read-only mind'' [Gosper's immortal quote from HAKMEM item 154, out of context] you would not like to put any arbitrary upper limit on the length of your symbols. In practice this often means you will build many short symbols and a few long symbols. At the time you are reading a symbol you don't know how long it is. One traditional method is to read a symbol into a buffer, @code{realloc()}ating the buffer every time you try to read a symbol that is longer than the buffer. This is beaut, but you still will want to copy the symbol from the buffer to a more permanent symbol-table entry say about half the time. With obstacks, you can work differently. Use one obstack for all symbol names. As you read a symbol, grow the name in the obstack gradually. When the name is complete, finalize it. Then, if the symbol exists already, free the newly read name. The way we do this is to take a large chunk, allocating memory from low addresses. When you want to build a symbol in the chunk you just add chars above the current ``high water mark'' in the chunk. When you have finished adding chars, because you got to the end of the symbol, you know how long the chars are, and you can create a new object. Mostly the chars will not burst over the highest address of the chunk, because you would typically expect a chunk to be (say) 100 times as long as an average object. In case that isn't clear, when we have enough chars to make up the object, @emph{they are already contiguous in the chunk} (guaranteed) so we just point to it where it lies. No moving of chars is needed and this is the second win: potentially long strings need never be explicitly shuffled. Once an object is formed, it does not change its address during its lifetime. When the chars burst over a chunk boundary, we allocate a larger chunk, and then copy the partly formed object from the end of the old chunk to the beginning of the new larger chunk. We then carry on accreting characters to the end of the object as we normally would. A special version of grow is provided to add a single char at a time to a growing object. Summary: @itemize @bullet @item We allocate large chunks. @item We carve out one object at a time from the current chunk. @item Once carved, an object never moves. @item We are free to append data of any size to the currently growing object. @item Exactly one object is growing in an obstack at any one time. @item You can run one obstack per control block. @item You may have as many control blocks as you dare. @item Because of the way we do it, you can `unwind' a obstack back to a previous state. (You may remove objects much as you would with a stack.) @end itemize The obstack data structure is used in many places in the GNU C++ compiler. Differences from the the GNU C version @enumerate @item The obvious differences stemming from the use of classes and inline functions instead of structs and macros. The C @code{init} and @code{begin} macros are replaced by constructors. @item Overloaded function names are used for grow (and others), rather than the C @code{grow}, @code{grow0}, etc. @item All dynamic allocation uses the the built-in @code{new} operator. This restricts flexibility by a little, but maintains compatibility with usual C++ conventions. @item There are now two versions of finish: @enumerate @item finish() behaves like the C version. @item finish(char terminator) adds @code{terminator}, and then calls @code{finish()}. This enables the normal invocation of @code{finish(0)} to wrap up a string being grown character-by-character. @end enumerate @item There are special versions of grow(const char* s) and copy(const char* s) that add the null-terminated string @code{s} after computing its length. @item The shrink and contains functions are provided. @end enumerate @node AllocRing, String, Obstack, Top @chapter The AllocRing class An AllocRing is a bounded ring (circular list), each of whose elements contains a pointer to some space allocated via @code{new char[some_size]}. The entries are used cyclicly. The size, n, of the ring is fixed at construction. After that, every nth use of the ring will reuse (or reallocate) the same space. AllocRings are needed in order to temporarily hold chunks of space that are needed transiently, but across constructor-destructor scopes. They mainly useful for storing strings containing formatted characters to print acrosss various functions and coercions. These strings are needed across routines, so may not be deleted in any one of them, but should be recovered at some point. In other words, an AllocRing is an extremely simple minded garbage collection mechanism. The GNU C++ library uses one AllocRing for such formatting purposes. AllocRings are probably not very useful otherwise. Support includes: @table @code @item AllocRing a(int n) constructs an Alloc ring with n entries, all null. @item void* mem = a.alloc(sz) moves the ring pointer to the next entry, and reuses the space if their is enough, also allocates space via new char[sz]. @item int present = a.contains(void* ptr) returns true if ptr is held in one of the ring entries. @item a.clear() deletes all space pointed to in any entry. This is called automatically upon destruction. @item a.free(void* ptr) If ptr is one of the entries, calls delete of the pointer, and resets to entry pointer to null. @end table @node String, Integer, AllocRing, Top @chapter The String class The @code{String} class is designed to extend GNU C++ to support string processing capabilities similar to those in languages like Awk. The class provides facilities that ought to be convenient and efficient enough to be useful replacements for @code{char*} based processing via the C string library (i.e., @code{strcpy, strcmp,} etc.) in many applications. Many details about String representations are described in the Representation section. A separate @code{SubString} class supports substring extraction and modification operations. This is implemented in a way that user programs never directly construct or represent substrings, which are only used indirectly via String operations. Another separate class, @code{Regex} is also used indirectly via String operations in support of regular expression searching, matching, and the like. The Regex class is based entirely on the GNU emacs regex functions. Refer to the GNU Emacs documentation for details about regular expression syntax, etc. See the internal documentation in files @file{regex.h} and @file{regex.c} for implementation details. @section Constructors Strings are initialized and assigned as in the following examples: @table @code @item String x; String y = 0; String z = ""; Set x, y, and z to the nil string. Note that either 0 or "" may always be used to refer to the nil string. @item String x = "Hello"; String y("Hello"); Set x and y to a copy of the string "Hello". @item String x = 'A'; String y('A'); Set x and y to the string value "A" @item String u = x; String v(x); Set u and v to the same string as String x @item String u = x.at(1,4); String v(x.at(1,4)); Set u and v to the length 4 substring of x starting at position 1 (counting indexes from 0). @item String x("abc", 2); Sets x to "ab", i.e., the first 2 characters of "abc". @item String x = dec(20); Sets x to "20". As here, Strings may be initialized or assigned the results of any @code{char*} function. @end table There are no directly accessible forms for declaring SubString variables. The declaration @code{Regex r("[a-zA-Z_][a-zA-Z0-9_]*");} creates a compiled regular expression suitable for use in String operations described below. (In this case, one that matches any C++ identifier). The first argument may also be a String. Be careful in distinguishing the role of backslashes in quoted GNU C++ char* constants versus those in Regexes. For example, a Regex that matches either one or more tabs or all strings beginning with "ba" and ending with any number of occurrences of "na" could be declared as @code{Regex r = "\\(\t+\\)\\|\\(ba\\(na\\)*\\)"} Note that only one backslash is needed to signify the tab, but two are needed for the parenthesization and virgule, since the GNU C++ lexical analyzer decodes and strips backslashes before they are seen by Regex. There are three additional optional arguments to the Regex constructor that are less commonly useful: @table @code @item fast (default 0) @code{fast} may be set to true (1) if the Regex should be "fast-compiled". This causes an additional compilation step that is generally worthwhile if the Regex will be used many times. @item bufsize (default max(40, length of the string)) This is an estimate of the size of the internal compiled expression. Set it to a larger value if you know that the expression will require a lot of space. If you do not know, do not worry: realloc is used if necessary. @item transtable (default none == 0) The address of a byte translation table (a char[256]) that translates each character before matching. @end table As a convenience, several Regexes are predefined and usable in any program. Here are their declarations from @file{String.h}. @example extern Regex RXwhite; // = "[ \n\t]+" extern Regex RXint; // = "-?[0-9]+" extern Regex RXdouble; // = "-?\\(\\([0-9]+\\.[0-9]*\\)\\| // \\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\) // \\([eE][---+]?[0-9]+\\)?" extern Regex RXalpha; // = "[A-Za-z]+" extern Regex RXlowercase; // = "[a-z]+" extern Regex RXuppercase; // = "[A-Z]+" extern Regex RXalphanum; // = "[0-9A-Za-z]+" extern Regex RXidentifier; // = "[A-Za-z_][A-Za-z0-9_]*" @end example @section Examples Most @code{String} class capabilities are best shown via example. The examples below use the following declarations. @example String x = "Hello"; String y = "world"; String n = "123"; String z; char* s = ","; String lft, mid, rgt; Regex r = "e[a-z]*o"; Regex r2("/[a-z]*/"); char c; int i, pos, len; double f; String words[10]; words[0] = "a"; words[1] = "b"; words[2] = "c"; @end example @section Comparing, Searching and Matching The usual lexicographic relational operators (@code{==, !=, <, <=, >, >=}) are defined. A functional form @code{compare(String, String)} is also provided, as is @code{fcompare(String, String)}, which compares Strings without regard for upper vs. lower case. All other matching and searching operations are based on some form of the (non-public) @code{match} and @code{search} functions. @code{match} and @code{search} differ in that @code{match} attempts to match only at the given starting position, while @code{search} starts at the position, and then proceeds left or right looking for a match. As seen in the following examples, the second optional @code{startpos} argument to functions using @code{match} and @code{search} specifies the starting position of the search: If non-negative, it results in a left-to-right search starting at position @code{startpos}, and if negative, a right-to-left search starting at position @code{x.length() + startpos}. In all cases, the index returned is that of the beginning of the match, or -1 if there is no match. Three String functions serve as front ends to @code{search} and @code{match}. @code{index} performs a search, returning the index, @code{matches} performs a match, returning nonzero (actually, the length of the match) on success, and @code{contains} is a boolean function performing either a search or match, depending on whether an index argument is provided: @table @code @item x.index("lo") returns the zero-based index of the leftmost occurrence of substring "lo" (3, in this case). The argument may be a String, SubString, char, char*, or Regex. @item x.index("l", 2) returns the index of the first of the leftmost occurrence of "l" found starting the search at position x[2], or 2 in this case. @item x.index("l", -1) returns the index of the rightmost occurrence of "l", or 3 here. @item x.index("l", -3) returns the index of the rightmost occurrence of "l" found by starting the search at the 3rd to the last position of x, returning 2 in this case. @item pos = r.search("leo", 3, len, 0) returns the index of r in the @code{char*} string of length 3, starting at position 0, also placing the length of the match in reference parameter len. @item x.contains("He") returns nonzero if the String x contains the substring "He". The argument may be a String, SubString, char, char*, or Regex. @item x.contains("el", 1) returns nonzero if x contains the substring "el" at position 1. As in this example, the second argument to @code{contains}, if present, means to match the substring only at that position, and not to search elsewhere in the string. @item x.contains(RXwhite); returns nonzero if x contains any whitespace (space, tab, or newline). Recall that @code{RXwhite} is a global whitespace Regex. @item x.matches("lo", 3) returns nonzero if x starting at position 3 exactly matches "lo", with no trailing characters (as it does in this example). @item x.matches(r) returns nonzero if String x as a whole matches Regex r. @item int f = x.freq("l") returns the number of distinct, nonoverlapping matches to the argument (2 in this case). @end table @section Substring extraction Substrings may be extracted via the @code{at}, @code{before}, @code{through}, @code{from}, and @code{after} functions. These behave as either lvalues or rvalues. @table @code @item z = x.at(2, 3) sets String z to be equal to the length 3 substring of String x starting at zero-based position 2, setting z to "llo" in this case. A nil String is returned if the arguments don't make sense. @item x.at(2, 2) = "r" Sets what was in positions 2 to 3 of x to "r", setting x to "Hero" in this case. As indicated here, SubString assignments may be of different lengths. @item x.at("He") = "je"; x("He") is the substring of x that matches the first occurrence of it's argument. The substitution sets x to "jello". If "He" did not occur, the substring would be nil, and the assignment would have no effect. @item x.at("l", -1) = "i"; replaces the rightmost occurrence of "l" with "i", setting x to "Helio". @item z = x.at(r) sets String z to the first match in x of Regex r, or "ello" in this case. A nil String is returned if there is no match. @item z = x.before("o") sets z to the part of x to the left of the first occurrence of "o", or "Hell" in this case. The argument may also be a String, SubString, or Regex. @item x.before("ll") = "Bri"; sets the part of x to the left of "ll" to "Bri", setting x to "Brillo". @item z = x.before(2) sets z to the part of x to the left of x[2], or "He" in this case. @item z = x.after("Hel") sets z to the part of x to the right of "Hel", or "lo" in this case. @item z = x.through("el") sets z to the part of x up and including "el", or "Hel" in this case. @item z = x.from("el") sets z to the part of x from "el" to the end, or "ello" in this case. @item x.after("Hel") = "p"; sets x to "Help"; @item z = x.after(3) sets z to the part of x to the right of x[3] or "o" in this case. @item z = " ab c"; z = z.after(RXwhite) sets z to the part of its old string to the right of the first group of whitespace, setting z to "ab c"; Use gsub(below) to strip out multiple occurrences of whitespace or any pattern. @item x[0] = 'J'; sets the first element of x to 'J'. x[i] returns a reference to the ith element of x, or triggers an error if i is out of range. @item common_prefix(x, "Help") returns the String containing the common prefix of the two Strings or "Hel" in this case. @item common_suffix(x, "to") returns the String containing the common suffix of the two Strings or "o" in this case. @end table @section Concatenation @table @code @item z = x + s + ' ' + y.at("w") + y.after("w") + "."; sets z to "Hello, world." @item x += y; sets x to "Helloworld" @item cat(x, y, z) A faster way to say z = x + y. @item cat(z, y, x, x) Double concatenation; A faster way to say x = z + y + x. @item y.prepend(x); A faster way to say y = x + y. @item z = replicate(x, 3); sets z to "HelloHelloHello". @item z = join(words, 3, "/") sets z to the concatenation of the first 3 Strings in String array words, each separated by "/", setting z to "a/b/c" in this case. The last argument may be "" or 0, indicating no separation. @end table @section Other manipulations @table @code @item z = "this string has five words"; i = split(z, words, 10, RXwhite); sets up to 10 elements of String array words to the parts of z separated by whitespace, and returns the number of parts actually encountered (5 in this case). Here, words[0] = "this", words[1] = "string", etc. The last argument may be any of the usual. If there is no match, all of z ends up in words[0]. The words array is @emph{not} dynamically created by split. @item int nmatches x.gsub("l","ll") substitutes all original occurrences of "l" with "ll", setting x to "Hellllo". The first argument may be any of the usual, including Regex. If the second argument is "" or 0, all occurrences are deleted. gsub returns the number of matches that were replaced. @item z = x + y; z.del("loworl"); deletes the leftmost occurrence of "loworl" in z, setting z to "Held". @item z = reverse(x) sets z to the reverse of x, or "olleH". @item z = upcase(x) sets z to x, with all letters set to uppercase, setting z to "HELLO" @item z = downcase(x) sets z to x, with all letters set to lowercase, setting z to "hello" @item z = capitalize(x) sets z to x, with the first letter of each word set to uppercase, and all others to lowercase, setting z to "Hello" @item x.reverse(), x.upcase(), x.downcase(), x.capitalize() in-place, self-modifying versions of the above. @end table @section Reading, Writing and Conversion @table @code @item cout << x writes out x. @item cout << x.at(2, 3) writes out the substring "llo". @item cin >> x reads a whitespace-bounded string into x. @item x.length() returns the length of String x (5, in this case). @item s = (char*)x can be used to extract the @code{char*} char array. This coercion is useful for sending a String as an argument to any function expecting a @code{const char*} argument (like @code{atoi}, and @code{File::open}). This operator must be used with care. Strings should not be @emph{modified} by nonmember functions. Doing so may corrupt their representation. The conversion is defined to return a const value so that GNU C++ will produce warning and/or error messages if changes are attempted. @end table @node Integer, Rational, String, Top @chapter The Integer class. The @code{Integer} class provides multiple precision integer arithmetic facilities. Some representation details are discussed in the Representation section. @code{Integers} may be up to @code{b * ((1 << b) - 1)} bits long, where @code{b} is the number of bits per short (typically 1048560 bits when @code{b = 16}). The implementation assumes that a @code{long} is at least twice as long as a @code{short}. This assumption hides beneath almost all primitive operations, and would be very difficult to change. It also relies on correct behavior of @emph{unsigned} arithmetic operations. Some of the arithmetic algorithms are very loosely based on those provided in the MIT Scheme @file{bignum.c} release, which is Copyright (c) 1987 Massachusetts Institute of Technology. Their use here falls within the provisions described in the Scheme release. Integers may be constructed in the following ways: @table @code @item Integer x; Declares an uninitialized Integer. @item Integer x = 2; Integer y(2); Set x and y to the Integer value 2; @item Integer u(x); Integer v = x; Set u and v to the same value as x. @end table @code{Integers} may be coerced back into longs via the @code{long} coercion operator. If the Integer cannot fit into a long, this returns MINLONG or MAXLONG (depending on the sign) where MINLONG is the most negative, and MAXLONG is the most positive representable long. The member function @code{fits_in_long()} may be used to test this. @code{Integers} may also be coerced into @code{doubles}, with potential loss of precision. @code{+/-HUGE} is returned if the Integer cannot fit into a double. @code{fits_in_double()} may be used to test this. All of the usual arithmetic operators are provided (@code{+, -, *, /, %, +=, ++, -=, --, *=, /=, %=, ==, !=, <, <=, >, >=}). All operators support special versions for mixed arguments of Integers and regular C++ longs in order to avoid useless coercions, as well as to allow automatic promotion of shorts and ints to longs, so that they may be applied without additional Integer coercion operators. The only operators that behave differently than the corresponding int or long operators are @code{++} and @code{--}. Because C++ does not distinguish prefix from postfix application, these are declared as @code{void} operators, so that no confusion can result from applying them as postfix. Thus, for Integers x and y, @code{ ++x; y = x; } is correct, but @code{ y = ++x; } and @code{ y = x++; } are not. Bitwise operators (@code{~, &, |, ^, <<, >>, &=, |=, ^=, <<=, >>=}) are also provided. However, these operate on sign-magnitude, rather than two's complement representations. The sign of the result is arbitrarily taken as the sign of the first argument. For example, @code{Integer(-3) & Integer(5)} returns @code{Integer(-1)}, not -3, as it would using two's complement. Also, @code{~}, the complement operator, complements only those bits needed for the representation. Bit operators are also provided in the BitSet and BitString classes. One of these classes should be used instead of Integers when the results of bit manipulations are not interpreted numerically. The following utility functions are also provided. (All arguments are Integers unless otherwise noted). @table @code @item void divide(x, y, q, r); Sets q to the quotient and r to the remainder of x and y. (q and r are returned by reference). @item Integer pow(Integer x, Integer p) returns x raised to the power p. @item Integer Ipow(long x, long p) returns x raised to the power p. @item Integer gcd(x, y) returns the greatest common divisor of x and y. @item Integer lcm(x, y) returns the least common multiple of x and y. @item Integer abs(x); returns the absolute value of x. @item void x.negate(); negates x. @item Integer sqr(x) returns x * x; @item Integer sqrt(x) returns the floor of the square root of x. @item long lg(x); returns the floor of the base 2 logarithm of abs(x) @item int sign(x) returns -1 if x is negative, 0 if zero, else +1. Using @code{if (sign(x) == 0)} is a generally faster method of testing for zero than using relational operators. @item int even(x) returns true if x is an even number @item int odd(x) returns true if x is an odd number. @item void setbit(Integer& x, long b) sets the b'th bit (counting right-to-left from zero) of x to 1. @item void clearbit(Integer& x, long b) sets the b'th bit of x to 0. @item int testbit(Integer x, long b) returns true if the b'th bit of x is 1. @item Integer atoI(char* asciinumber, int base = 10); converts the base base char* string into its Integer form. @item char* Itoa(x, int base = 10, int width = 0); returns a pointer to the ascii string value of x as a base @code{base} number, in field width at least @code{width}. @item ostream << x; prints x in base ten format. @item istream >> x; reads x as a base ten number. @item int compare(Integer x, Integer y) returns a negative number if xy. @item int ucompare(Integer x, Integer y) like compare, but performs unsigned comparison. @item add(x, y, z) A faster way to say z = x + y. @item sub(x, y, z) A faster way to say z = x - y. @item mul(x, y, z) A faster way to say z = x * y. @item div(x, y, z) A faster way to say z = x / y. @item mod(x, y, z) A faster way to say z = x % y. @item and(x, y, z) A faster way to say z = x & y. @item or(x, y, z) A faster way to say z = x | y. @item xor(x, y, z) A faster way to say z = x ^ y. @item lshift(x, y, z) A faster way to say z = x << y. @item rshift(x, y, z) A faster way to say z = x >> y. @item pow(x, y, z) A faster way to say z = pow(x, y). @item complement(x, z) A faster way to say z = ~x. @item negate(x, z) A faster way to say z = -x. @end table @node Rational, Complex, Integer, Top @chapter The Rational Class Class @code{Rational} provides multiple precision rational number arithmetic. All rationals are maintained in simplest form (i.e., with the numerator and denominator relatively prime, and with the denominator strictly positive). Rational arithmetic and relational operators are provided (@code{+, -, *, /, +=, -=, *=, /=, ==, !=, <, <=, >, >=}). Operations resulting in a rational number with zero denominator trigger an exception. Rationals may be constructed and used in the following ways: @table @code @item Rational x; Declares an uninitialized Rational. @item Rational x = 2; Rational y(2); Set x and y to the Rational value 2/1; @item Rational x(2, 3); Sets x to the Rational value 2/3; @item Rational x = 1.2; Sets x to a Rational value close to 1.2. Any double precision value may be used to construct a Rational. The Rational will possess exactly as much precision as the double. Double values that do not have precise floating point equivalents (like 1.2) produce similarly imprecise rational values. @item Rational x(Integer(123), Integer(4567)); Sets x to the Rational value 123/4567. @item Rational u(x); Rational v = x; Set u and v to the same value as x. @item double(Rational x) A Rational may be coerced to a double with potential loss of precision. +/-HUGE is returned if it will not fit. @item Rational abs(x) returns the absolute value of x. @item void x.negate() negates x. @item void x.invert() sets x to 1/x. @item int sign(x) returns 0 if x is zero, 1 if positive, and -1 if negative. @item Rational sqr(x) returns x * x. @item Rational pow(x, Integer y) returns x to the y power. @item Integer x.numerator() returns the numerator. @item Integer x.denominator() returns the denominator. @item Integer floor(x) returns the greatest Integer less than x. @item Integer ceil(x) returns the least Integer greater than x. @item Integer trunc(x) returns the Integer part of x. @item Integer round(x) returns the nearest Integer to x. @item int compare(x, y) returns a negative, zero, or positive number signifying whether x is less than, equal to, or greater than y. @item ostream << x; prints x in the form num/den, or just num if the denominator is one. @item istream >> x; reads x in the form num/den, or just num in which case the denominator is set to one. @item add(x, y, z) A faster way to say z = x + y. @item sub(x, y, z) A faster way to say z = x - y. @item mul(x, y, z) A faster way to say z = x * y. @item div(x, y, z) A faster way to say z = x / y. @item pow(x, y, z) A faster way to say z = pow(x, y). @item negate(x, z) A faster way to say z = -x. @end table @node Complex, Fix, Rational, Top @chapter The Complex class. Class @code{Complex} is implemented in a way similar to that described by Stroustrup. In keeping with libg++ conventions, the class is named @code{Complex}, not @code{complex}. Complex arithmetic and relational operators are provided (@code{+, -, *, /, +=, -=, *=, /=, ==, !=}). Attempted division by (0, 0) triggers an exception. Complex numbers may be constructed and used in the following ways: @table @code @item Complex x; Declares an uninitialized Complex. @item Complex x = 2; Complex y(2.0); Set x and y to the Complex value (2.0, 0.0); @item Complex x(2, 3); Sets x to the Complex value (2, 3); @item Complex u(x); Complex v = x; Set u and v to the same value as x. @item double real(Complex& x); returns the real part of x. @item double imag(Complex& x); returns the imaginary part of x. @item double abs(Complex& x); returns the magnitude of x. @item double norm(Complex& x); returns the square of the magnitude of x. @item double arg(Complex& x); returns the argument (amplitude) of x. @item Complex polar(double r, double t = 0.0); returns a Complex with abs of r and arg of t. @item Complex conj(Complex& x); returns the complex conjugate of x. @item Complex cos(Complex& x); returns the complex cosine of x. @item Complex sin(Complex& x); returns the complex sine of x. @item Complex cosh(Complex& x); returns the complex hyperbolic cosine of x. @item Complex sinh(Complex& x); returns the complex hyperbolic sine of x. @item Complex exp(Complex& x); returns the exponential of x. @item Complex log(Complex& x); returns the natural log of x. @item Complex pow(Complex& x, long p); returns x raised to the p power. @item Complex pow(Complex& x, Complex& p); returns x raised to the p power. @item Complex sqrt(Complex& x); returns the square root of x. @item ostream << x; prints x in the form (re, im). @item istream >> x; reads x in the form (re, im), or just (re) or re in which case the imaginary part is set to zero. @end table @node Fix, Bit, Complex, Top @chapter Fixed precision numbers Classes @code{Fix16}, @code{Fix24}, @code{Fix32}, and @code{Fix48} support operations on 16, 24, 32, or 48 bit quantities that are considered as real numbers in the range [-1, +1). Such numbers are often encountered in digital signal processing applications. The classes classes may be be used in isolation or together. Class @code{Fix32} operations are entirely self-contained. Class @code{Fix16} operations are self-contained except that the multiplication operation @code{Fix16 * Fix16} returns a @code{Fix32}. @code{Fix24} and @code{Fix48} are similarly related. The standard arithmetic and relational operations are supported (@code{=, +, -, *, /, <<, >>, +=, -=, *=, /=, <<=, >>=, ==, !=, <, <=, >, >=}) All operations include provisions for special handling in cases where the result exceeds +/- 1.0. There are two cases that may be handled separately: ``overflow'' where the results of addition and subtraction operations go out of range, and all other ``range errors'' in which resulting values go off-scale (as with division operations, and assignment or initialization with off-scale values). In signal processing applications, it is often useful to handle these two cases differently. Handlers take one argument, a reference to the integer mantissa of the offending value, which may then be manipulated. In cases of overflow, this value is the result of the (integer) arithmetic computation on the mantissa; in others it is a fully saturated (i.e., most positive or most negative) value. Handling may be reset to any of several provided functions or any other user-defined function via @code{set_overflow_handler} and @code{set_range_error_handler}. The provided functions for @code{Fix16} are as follows (corresponding functions are also supported for the others). @table @code @item Fix16_overflow_saturate The default overflow handler. Results are ``saturated'': positive results are set to the largest representable value (binary 0.111111...), and negative values to -1.0. @item Fix16_ignore Performs no action. For overflow, this will allow addition and subtraction operations to ``wrap around'' in the same manner as integer arithmetic, and for saturation, will leave values saturated. @item Fix16_overflow_warning_saturate Prints a warning message on standard error, then saturates the results. @item Fix16_warning The default range_error handler. Prints a warning message on standard error; otherwise leaving the argument unmodified. @item Fix16_abort prints an error message on standard error, then aborts execution. @end table In addition to arithmetic operations, the following are provided: @table @code @item Fix16 a = 0.5; Constructs fixed precision objects from double precision values. Attempting to initialize to a value outside the range invokes the range_error handler, except, as a convenience, initialization to 1.0 sets the variable to the most positive representable value (binary 0.1111111...) without invoking the handler. @item short& mantissa(a); long& mantissa(b); return a * pow(2, 15) or b * pow(2, 31) as an integer. These are returned by reference, to enable ``manual'' data manipulation. @item double value(a); double value(b); return a or b as floating point numbers. @end table @node Bit, Random, Fix, Top @chapter Classes for Bit manipulation libg++ provides several different classes supporting the use and manipulation of collections of bits in different ways. @itemize @bullet @item Class @code{Integer} provides ``integer'' semantics. It supports manipulation of bits in ways that are often useful when treating bit arrays as numerical (integer) quantities. This class is described elsewhere. @item Class @code{BitSet} provides ``set'' semantics. It supports operations useful when treating collections of bits as representing potentially infinite sets of integers. @item Class @code{BitString} provides ``string'' (or ``vector'') semantics. It supports operations useful when treating collections of bits as strings of zeros and ones. @end itemize These classes also differ in the following ways: @itemize @bullet @item BitSets are logically infinite. Their space is dynamically altered to adjust to the smallest number of consecutive bits actually required to represent the sets. Integers also have this property. BitStrings are logically finite, but their sizes are internally dynamically managed to maintain proper length. This means that, for example, BitStrings are concatenatable while BitSets and Integers are not. @item While all classes support basic unary and binary operations @code{~, &, |, ^, -}, the semantics differ. BitSets perform bit operations that precisely mirror those for infinite sets. For example, complementing an empty BitSet returns one representing an infinite number of set bits. Operations on BitStrings and Integers operate only on those bits actually present in the representation. For BitStrings and Integers, the the @code{&} operation returns a BitString with a length equal to the minimum length of the operands, and @code{|, ^} return one with length of the maximum. @item Only BitStrings support substring extraction and bit pattern matching. @end itemize @section BitSet Bitsets are objects that contain logically infinite sets of nonnegative integers. Representational details are discussed in the Representation chapter. Because they are logically infinite, all BitSets possess a trailing, infinitely replicated 0 or 1 bit, called the ``virtual bit'', and indicated via 0* or 1*. BitSets may be constructed as follows: @table @code @item BitSet a; declares an empty BitSet. @item BitSet a = atoBitSet("001000"); sets a to the BitSet 0010*, reading left-to-right. The ``0*'' indicates that the set ends with an infinite number of zero (clear) bits. @item BitSet a = atoBitSet("00101*"); sets a to the BitSet 00101*, where ``1*'' means that the set ends with an infinite number of one (set) bits. @item BitSet a = longtoBitSet(23); sets a to the BitSet 111010*, the binary representation of decimal 23. @end table The following functions and operators are provided (Assume the declaration of BitSets a = 0011010*, b = 101101*, throughout, as examples). @table @code @item ~a returns the complement of a, or 1100101* in this case. @item a.complement() sets a to ~a. @item a & b; a &= b; returns a intersected with b, or 0011010*. @item a | b; a |= b; returns a unioned with b, or 1011111*. @item a - b; a -= b; returns the set difference of a and b, or 000010*. @item a ^ b; a ^= b; returns the symmetric difference of a and b, or 1000101*. @item a.empty() returns true if a is an empty set. @item a == b; returns true if a and b contain the same set. @item a <= b; returns true if a is a subset of b. @item a < b; returns true if a is a proper subset of b; @item a != b; a >= b; a > b; are the converses of the above. @item a.set(7) sets the 7th (counting from 0) bit of a, setting a to 001111010* @item a.clear(2) clears the 2nd bit bit of a, setting a to 00011110* @item a.clear() clears all bits of a; @item a.set() sets all bits of a; @item a.invert(0) complements the 0th bit of a, setting a to 10011110* @item a.set(0,1) sets the 0th through 1st bits of a, setting a to 110111110* The two-argument versions of clear and invert are similar. @item a.test(3) returns true if the 3rd bit of a is set. @item a.test(3, 5) returns true if any of bits 3 through 5 are set. @item int i = a[3]; a[3] = 0; The subscript operator allows bits to be inspected and changed via standard subscript semantics, using a friend class BitSetBit. The use of the subscript operator a[i] rather than a.test(i) requires somewhat greater overhead. @item a.first(1) or a.first() returns the index of the first set bit of a (2 in this case), or -1 if no bits are set. @item a.first(0) returns the index of the first clear bit of a (0 in this case), or -1 if no bits are clear. @item a.next(2, 1) or a.next(2) returns the index of the next bit after position 2 that is set (3 in this case) or -1. @code{first} and @code{next} may be used as iterators, as in @code{for (int i = a.first(); i >= 0; i = a.next(i))...}. @item a.last(1) returns the index of the rightmost set bit, or -1 if there or no set bits or all set bits. @item a.previous(3, 0) returns the index of the previous clear bit before position 3. @item a.count(1) returns the number of set bits in a, or -1 if there are an infinite number. @item a.virtual_bit() returns the trailing (infinitely replicated) bit of a. @item a = atoBitSet("ababX", 'a', 'b', 'X'); converts the char* string into a bitset, with 'a' denoting false, 'b' denoting true, and 'X' denoting infinite replication. @item char* s = BitSettoa(a, '-', '.', 0) returns a pointer to a (static) location holding a represented with '-' for falses, '.' for trues, and no replication marker. @item diff(x, y, z) A faster way to say z = x - y. @item and(x, y, z) A faster way to say z = x & y. @item or(x, y, z) A faster way to say z = x | y. @item xor(x, y, z) A faster way to say z = x ^ y. @item complement(x, z) A faster way to say z = ~x. @end table @section BitString BitStrings are objects that contain arbitrary-length strings of zeroes and ones. BitStrings possess some features that make them behave like sets, and others that behave as strings. They are useful in applications (such as signature-based algorithms) where both capabilities are needed. Representational details are discussed in the Representation chapter. Most capabilities are exact analogs of those supported in the BitSet and String classes. A BitSubString is used with substring operations along the same lines as the String SubString class. A BitPattern class is used for masked bit pattern searching. Only a default constructor is supported. The declaration @code{BitString a;} initializes a to be an empty BitString. BitStrings may often be initialized via @code{atoBitString} and @code{longtoBitString}. Set operations (@code{ ~, complement, &, &=, |, |=, -, ^, ^=}) behave just as the BitSet versions, except that there is no ``virtual bit'': complementing complements only those bits in the BitString, and all binary operations across unequal length BitStrings assume a virtual bit of zero. The @code{&} operation returns a BitString with a length equal to the minimum length of the operands, and @code{|, ^} return one with length of the maximum. Set-based relational operations (@code{==, !=, <=, <, >=, >}) follow the same rules. A string-like lexicographic comparison function, @code{lcompare}, tests the lexicographic relation between two BitStrings. For example, lcompare(1100, 0101) returns 1, since the first BitString starts with 1 and the second with 0. Individual bit setting, testing, and iterator operations (@code{set, clear, invert, test, first, next, last, previous}) are also like those for BitSets. BitStrings are automatically expanded when setting bits at positions greater than their current length. The string-based capabilities are just as those for class String. BitStrings may be concatenated (@code{+, +=}), searched (@code{index, contains, matches}), and extracted into BitSubStrings (@code{before, at, after}) which may be assigned and otherwise manipulated. Other string-based utility functions (@code{reverse, common_prefix, common_suffix}) are also provided. These have the same capabilities and descriptions as those for Strings. String-oriented operations can also be performed with a mask via class BitPattern. BitPatterns consist of two BitStrings, a pattern and a mask. On searching and matching, bits in the pattern that correspond to 0 bits in the mask are ignored. (The mask may be shorter than the pattern, in which case trailing mask bits are assumed to be 0). The pattern and mask are both public variables, and may be individually subjected to other bit operations. Converting to char* and printing (@code{(atoBitString, BitStringtoa, atoBitPattern, BitPatterntoa, ostream <<)}) are also as in BitSets, except that no virtual bit is used, and an 'X' in a BitPattern means that the pattern bit is masked out. The following features are unique to BitStrings. Assume declarations of BitString a = atoBitString("01010110") and b = atoBitSTring("1101"). @table @code @item a = b + c; Sets a to the concatenation of b and c; @item a = b + 0; a = b + 1; sets a to b, appended with a zero (one). @item a += b; appends b to a; @item a += 0; a += 1; appends a zero (one) to a. @item a << 2; a <<= 2 return a with 2 zeros prepended, setting a to 0001010110. (Note the necessary confusion of << and >> operators. For consistency with the integer versions, << shifts low bits to high, even though they are printed low bits first.) @item a >> 3; a >>= 3 return a with the first 3 bits deleted, setting a to 10110. @item a.left_trim(0) deletes all 0 bits on the left of a, setting a to 1010110. @item a.right_trim(0) deletes all trailing 0 bits of a, setting a to 0101011. @item cat(x, y, z) A faster way to say z = x + y. @item diff(x, y, z) A faster way to say z = x - y. @item and(x, y, z) A faster way to say z = x & y. @item or(x, y, z) A faster way to say z = x | y. @item xor(x, y, z) A faster way to say z = x ^ y. @item lshift(x, y, z) A faster way to say z = x << y. @item rshift(x, y, z) A faster way to say z = x >> y. @item complement(x, z) A faster way to say z = ~x. @end table @node Random, Data, Bit, Top @chapter Random Number Generators and related classes The two classes @code{RNG} and @code{Random} are used together to generate a variety of random number distributions. A distinction must be made between @emph{random number generators}, implemented by class @code{RNG}, and @emph{random number distributions}. A random number generator produces a series of randomly ordered bits. These bits can be used directly, or cast to other representations, such as a floating point value. A random number generator should produce a @emph{uniform} distribution. A random number distribution, on the other hand, uses the randomly generated bits of a generator to produce numbers from a distribution with specific properties. Each instance of @code{Random} uses an instance of class @code{RNG} to provide the raw, uniform distribution used to produce the specific distribution. Several instances of @code{Random} classes can share the same instance of @code{RNG}, or each instance can use its own copy. @section RNG Random distributions are constructed from members of class @code{RNG}, the actual random number generators. The @code{RNG} class contains no data; it only serves to define the interface to random number generators. The @code{RNG::asLong} member returns an unsigned long (typically 32 bits) of random bits. Applications that require a number of random bits can use this directly. More often, these random bits are transformed to a uniform random number: @example // // Return random bits converted to either a float or a double // float asFloat(); double asDouble(); @}; @end example @noindent using either @code{asFloat} or @code{asDouble}. It is intended that @code{asFloat} and @code{asDouble} return differing precisions; typically, @code{asDouble} will draw two random longwords and transform them into a legal @code{double}, while @code{asFloat} will draw a single longword and transform it into a legal @code{float}. These members are used by subclasses of the @code{Random} class to implement a variety of random number distributions. @section ACG Class @code{ACG} is a variant of a Linear Congruential Generator (Algorithm M) described in Knuth, @emph{Art of Computer Programming, Vol III}. This result is permuted with a Fibonacci Additive Congruential Generator to get good independence between samples. This is a very high quality random number generator, although it requires a fair amount of memory for each instance of the generator. The @code{ACG::ACG} constructor takes two parameters: the seed and the size. The seed is any number to be used as an initial seed. The performance of the generator depends on having a distribution of bits through the seed. If you choose a number in the range of 0 to 31, a seed with more bits is chosen. Other values are deterministically modified to give a better distribution of bits. This provides a good random number generator while still allowing a sequence to be repeated given the same initial seed. The @code{size} parameter determines the size of two tables used in the generator. The first table is used in the Additive Generator; see the algorithm in Knuth for more information. In general, this table is @code{size} longwords long. The default value, used in the algorithm in Knuth, gives a table of 220 bytes. The table size affects the period of the generators; smaller values give shorter periods and larger tables give longer periods. The smallest table size is 7 longwords, and the longest is 98 longwords. The @code{size} parameter also determines the size of the table used for the Linear Congruential Generator. This value is chosen implicitly based on the size of the Additive Congruential Generator table. It is two powers of two larger than the power of two that is larger than @code{size}. For example, if @code{size} is 7, the ACG table is 7 longwords and the LCG table is 128 longwords. Thus, the default size (55) requires 55 + 256 longwords, or 1244 bytes. The largest table requires 2440 bytes and the smallest table requires 100 bytes. Applications that require a large number of generators or applications that aren't so fussy about the quality of the generator may elect to use the @code{MLCG} generator. @section MLCG The @code{MLCG} class implements a @emph{Multiplicative Linear Congruential Generator}. In particular, it is an implementation of the double MLCG described in @emph{``Efficient and Portable Combined Random Number Generators''} by Pierre L'Ecuyer, appearing in @emph{Communications of the ACM, Vol. 31. No. 6}. This generator has a fairly long period, and has been statistically analyzed to show that it gives good inter-sample independence. The @code{MLCG::MLCG} constructor has two parameters, both of which are seeds for the generator. As in the @code{MLCG} generator, both seeds are modified to give a ``better'' distribution of seed digits. Thus, you can safely use values such as `0' or `1' for the seeds. The @code{MLCG} generator used much less state than the @code{ACG} generator; only two longwords (8 bytes) are needed for each generator. @section Random A random number generator may be declared by first declaring a @code{RNG} and then a @code{Random}. For example, @code{ACG gen(10, 20); NegativeExpntl rnd (1.0, &gen);} declares an additive congruential generator with seed 10 and table size 20, that is used to generate exponentially distributed values with mean of 1.0. The virtual member @code{Random::operator()} is the common way of extracting a random number from a particular distribution. The base class, @code{Random} does not implement @code{operator()}. This is performed by each of the subclasses. Thus, given the above declaration of @code{rnd}, new random values may be obtained via, for example, @code{double next_exp_rand = rnd();} Currently, the following subclasses are provided. @section Binomial The binomial distribution models successfully drawing items from a pool. The first parameter to the constructor, @code{n}, is the number of items in the pool, and the second parameter, @code{u}, is the probability of each item being successfully drawn. The member @code{asDouble} returns the number of samples drawn from the pool. Although it is not checked, it is assumed that @code{n>0} and @code{0 <= u <= 1}. The remaining members allow you to read and set the parameters. @section Erlang The @code{Erlang} class implements an Erlang distribution with mean @code{mean} and variance @code{variance}. @section Geometric The @code{Geometric} class implements a discrete geometric distribution. The first parameter to the constructor, @code{mean}, is the mean of the distribution. Although it is not checked, it is assumed that @code{0 <= mean <= 1}. @code{Geometric()} returns the number of uniform random samples that were drawn before the sample was larger than @code{mean}. This quantity is always greater than zero. @section HyperGeometric The @code{HyperGeometric} class implements the hypergeometric distribution. The first parameter to the constructor, @code{mean}, is the mean and the second, @code{variance}, is the variance. The remaining members allow you to inspect and change the mean and variance. @section NegativeExpntl The @code{NegativeExpntl} class implements the negative exponential distribution. The first parameter to the constructor is the mean. The remaining members allow you to inspect and change the mean. @section Normal The @code{Normal}class implements the normal distribution. The first parameter to the constructor, @code{mean}, is the mean and the second, @code{variance}, is the variance. The remaining members allow you to inspect and change the mean and variance. The @code{LogNormal} class is a subclass of @code{Normal}. @section LogNormal The @code{LogNormal}class implements the logarithmic normal distribution. The first parameter to the constructor, @code{mean}, is the mean and the second, @code{variance}, is the variance. The remaining members allow you to inspect and change the mean and variance. The @code{LogNormal} class is a subclass of @code{Normal}. @section Poisson The @code{Poisson} class implements the poisson distribution. The first parameter to the constructor is the mean. The remaining members allow you to inspect and change the mean. @section DiscreteUniform The @code{DiscreteUniform} class implements a uniform random variable over the closed interval ranging from @code{[low..high]}. The first parameter to the constructor is @code{low}, and the second is @code{high}, although the order of these may be reversed. The remaining members allow you to inspect and change @code{low} and @code{high}. @section Uniform The @code{Uniform} class implements a uniform random variable over the open interval ranging from @code{[low..high)}. The first parameter to the constructor is @code{low}, and the second is @code{high}, although the order of these may be reversed. The remaining members allow you to inspect and change @code{low} and @code{high}.@refill @section Weibull The @code{Weibull} class implements a weibull distribution with parameters @code{alpha} and @code{beta}. The first parameter to the class constructor is @code{alpha}, and the second parameter is @code{beta}. The remaining members allow you to inspect and change @code{alpha} and @code{beta}. @section RandomInteger The @code{RandomInteger} class is @emph{not} a subclass of Random, but a stand-alone integer-oriented class that is dependent on the RNG classes. RandomInteger returns random integers uniformly from the closed interval @code{[low..high]}. The first parameter to the constructor is @code{low}, and the second is @code{high}, although both are optional. The last argument is always a generator. Additional members allow you to inspect and change @code{low} and @code{high}. Random integers are generated using @code{asInt()} or @code{asLong()}. Operator syntax (@code{()}) is also available as a shorthand for @code{asLong()}. Because @code{RandomInteger} is often used in simulations for which uniform random integers are desired over a variety of ranges, @code{asLong()} and @code{asInt} have @code{high} as an optional argument. Using this optional argument produces a single value from the new range, but does not change the default range. @node Data, Curses, Random, Top @chapter Data Collection Libg++ currently provides two classes for @emph{data collection} and analysis of the collected data. @node Data, Curses, Random, Top @chapter Data collection @section SampleStatistic Class @code{SampleStatistic} provides a means of accumulating samples of @code{double} values and providing common sample statistics. Assume declaration of @code{double x}. @table @code @item SampleStatistic a; declares and initializes a. @item a.reset(); re-initializes a. @item a += x; adds sample x. @item int n = a.samples(); returns the number of samples. @item x = a.mean; returns the means of the samples. @item x = a.var() returns the sample variance of the samples. @item x = a.stdDev() returns the sample standard deviation of the samples. @item x = a.min() returns the minimum encountered sample. @item x = a.max() returns the maximum encountered sample. @item x = a.confidence(int p) returns the p-percent (0 <= p < 100) confidence interval. @item x = a.confidence(double p) returns the p-probability (0 <= p < 1) confidence interval. @end table @section SampleHistogram Class @code{SampleHistogram} is a derived class of @code{SampleStatistic} that supports collection and display of samples in bucketed intervals. It supports the following in addition to @code{SampleStatisic} operations. @table @code @item SampleHistogram h(double lo, double hi, double width); declares and initializes h to have buckets of size width from lo to hi. If the optional argument width is not specified, 10 buckets are created. The first bucket and also holds samples less than lo, and the last one holds samples greater than hi. @item int n = h.similarSamples(x) returns the number of samples in the same bucket as x. @item int n = h.inBucket(int i) returns the number of samples in bucket i. @item int b = h.buckets() returns the number of buckets. @item h.printBuckets(ostream s) prints bucket counts on ostream s. @item double bound = h.bucketThreshold(int i) returns the upper bound of bucket i. @end table @node Curses, List, Data, Top @chapter Curses-based classes The @code{CursesWindow} class is a repackaging of standard curses library features into a class. It relies on @file{curses.h}. The supplied @file{curses.h} is a fairly conservative declaration of curses library features, and does not include features like ``screen'' or X-window support. It is, for the most part, an adaptation, rather than an improvement of C-based @file{curses.h} files. The only substantive changes are the declarations of many functions as inline functions rather than macros, which was done solely to allow overloading. The @code{CursesWindow} class encapsulates curses window functions within a class. Only those functions that control windows are included: Terminal control functions and macros like @code{cbreak} are not part of the class. All @code{CursesWindows} member functions have names identical to the corresponding curses library functions, except that the ``w'' prefix is generally dropped. Descriptions of these functions may be found in your local curses library documentation. A @code{CursesWindow} may be declared via @table @code @item CursesWindow w(WINDOW* win) attaches w to the existing WINDOW* win. This is constructor is normally used only in the following special case. @item CursesWindow w(stdscr) attaches w to the default curses library standard screen window. @item CursesWindow w(int lines, int cols, int begin_y, int begin_x) attaches to an allocated curses window with the indicated size and screen position. @item CursesWindow sub(CursesWindow& w,int l,int c,int by,int bx,char ar='a') attaches to a subwindow of w created via the curses `subwin' command. If ar is sent as `r', the origin (by, bx) is relative to the parent window, else it is absolute. @end table The class maintains a static counter that is used in order to automatically call the curses library @code{initscr} and @code{endscr} functions at the proper times. These need not, and should not be called ``manually''. @code{CursesWindow}s maintain a tree of their subwindows. Upon destruction of a @code{CursesWindow}, all of their subwindows are also invalidated if they had not previously been destroyed. It is possible to traverse trees of subwindows via the following member functions @table @code @item CursesWindow* w.parent() returns a pointer to the parent of the subwindow, or 0 if there is none. @item CursesWindow* w.child() returns the first child subwindow of the window, or 0 if there is none. @item CursesWindow* w.sibling() returns the next sibling of the subwindow, or 0 if there is none. @end table For example, to call some function @code{visit} for all subwindows of a window, you could write @example void traverse(CursesWindow& w) @{ visit(w); if (w.child() != 0) traverse(*w.child); if (w.sibling() != 0) traverse(*w.sibling); @} @end example @node List, LinkList, Data, Top @chapter List classes Files @file{g++-include/List.hP} and @file{g++-include/List.ccP} provide pseudo-generic Lisp-type List classes. These lists are homogeneous lists, more similar to lists in statically typed functional languages like ML than Lisp, but support operations very similar to those found in Lisp. Any particular kind of list class may be generated via the @code{genclass} shell command. However, the implementation assumes that the base class supports an equality operator @code{==}. All equality tests use the @code{==} operator, and are thus equivalent to the use of @code{equal}, not @code{eq} in Lisp.@refill All list nodes are created dynamically, and managed via reference counts. @code{List} variables are actually pointers to these list nodes. Lists may also be traversed via Pixes. Supported operations are mirrored closely after those in Lisp. Generally, operations with functional forms are constructive, functional operations, while member forms (often with the same name) are sometimes procedural, possibly destructive operations. As with Lisp, destructive operations are supported. Programmers are allowed to change head and tail fields in any fashion, creating circular structures and the like. However, again as with Lisp, some operations implicitly assume that they are operating on pure lists, and may enter infinite loops when presented with improper lists. Also, the reference-counting storage management facility may fail to reclaim unused circularly-linked nodes. Several Lisp-like higher order functions are supported (e.g., @code{map}). Typedef declarations for the required functional forms are provided int the @file{.h} file. For purposes of illustration, assume the specification of class @code{intList}. Common Lisp versions of supported operations are shown in brackets for comparison purposes. @section Constructors and assignment @table @code @item intList a; [ (setq a nil) ] Declares a to be a nil intList. @item intList b(2); [ (setq b (cons 2 nil)) ] Declares b to be an intList with a head value of 2, and a nil tail. @item intList c(3, b); [ (setq c (cons 3 b)) ] Declares c to be an intList with a head value of 3, and b as its tail. @item b = a; [ (setq b a) ] Sets b to be the same list as a. @end table Assume the declarations of intLists a, b, and c in the following. @section List status @table @code @item a.null(); OR !a; [ (null a) ] returns true if a is null. @item a.valid(); [ (listp a) ] returns true if a is non-null. Inside a conditional test, the @code{void*} coercion may also be used as in @code{if (a) ...}. @item intList(); [ nil ] intList() may be used to null terminate a list, as in @code{intList f(int x) @{if (x == 0) return intList(); ... @} }. @item a.length(); [ (length a) ] returns the length of a. @item a.list_length(); [ (list-length a) ] returns the length of a, or -1 if a is circular. @end table @section heads and tails @table @code @item a.get(); OR a.head() [ (car a) ] returns a reference to the head field. @item a[2]; [ (elt a 2) ] returns a reference to the second (counting from zero) head field. @item a.tail(); [ (cdr a) ] returns the intList that is the tail of a. @item a.last(); [ (last a) ] returns the intList that is the last node of a. @item a.nth(2); [ (nth a 2) ] returns the intList that is the nth node of a. @item a.set_tail(b); [ (rplacd a b) ] sets a's tail to b. @item a.push(2); [ (push 2 a) ] equivalent to a = intList(2, a); @item int x = a.pop() [ (setq x (car a)) (pop a) ] returns the head of a, also setting a to its tail. @end table @section Constructive operations @table @code @item b = copy(a); [ (setq b (copy-seq a)) ] sets b to a copy of a. @item b = reverse(a); [ (setq b (reverse a)) ] Sets b to a reversed copy of a. @item c = concat(a, b); [ (setq c (concat a b)) ] Sets c to a concatenated copy of a and b. @item c = append(a, b); [ (setq c (append a b)) ] Sets c to a concatenated copy of a and b. All nodes of a are copied, with the last node pointing to b. @item b = map(f, a); [ (setq b (mapcar f a)) ] Sets b to a new list created by applying function f to each node of a. @item c = combine(f, a, b); Sets c to a new list created by applying function f to successive pairs of a and b. The resulting list has length the shorter of a and b. @item b = remove(x, a); [ (setq b (remove x a)) ] Sets b to a copy of a, omitting all occurrences of x. @item b = remove(f, a); [ (setq b (remove-if f a)) ] Sets b to a copy of a, omitting values causing function f to return true. @item b = select(f, a); [ (setq b (remove-if-not f a)) ] Sets b to a copy of a, omitting values causing function f to return false. @item c = merge(a, b, f); [ (setq c (merge a b f)) ] Sets c to a list containing the ordered elements (using the comparison function f) of the sorted lists a and b. @end table @section Destructive operations @table @code @item a.append(b); [ (rplacd (last a) b) ] appends b to the end of a. No new nodes are constructed. @item a.prepend(b); [ (setq a (append b a)) ] prepends b to the beginning of a. @item a.del(x); [ (delete x a) ] deletes all nodes with value x from a. @item a.del(f); [ (delete-if f a) ] deletes all nodes causing function f to return true. @item a.select(f); [ (delete-if-not f a) ] deletes all nodes causing function f to return false. @item a.reverse(); [ (nreverse a) ] reverses a in-place. @item a.sort(f); [ (sort a f) ] sorts a in-place using ordering (comparison) function f. @item a.apply(f); [ (mapc f a) ] Applies void function f (int x) to each element of a. @item a.subst(int old, int repl); [ (nsubst repl old a) ] substitutes repl for each occurrence of old in a. Note the different argument order than the Lisp version. @end table @section Other operations @table @code @item a.find(int x); [ (find x a) ] returns the intList at the first occurrence of x. @item a.find(b); [ (find b a) ] returns the intList at the first occurrence of sublist b. @item a.contains(int x); [ (member x a) ] returns true if a contains x. @item a.contains(b); [ (member b a) ] returns true if a contains sublist b. @item a.position(int x); [ (position x a) ] returns the zero-based index of x in a, or -1 if x does not occur. @item int x = a.reduce(f, int base); [ (reduce f a :initial-value base) ] Accumulates the result of applying int function f(int, int) to successive elements of a, starting with base. @end table @node LinkList, Stack, List, Top @chapter Linked Lists Files @file{g++-include/SLList.[h,cc]P} provide pseudo-generic singly linked lists. Files @file{g++-include/DLList.[h,cc]P} provide doubly linked lists. The lists are designed for the simple maintenance of elements in a linked structure, and do not provide the more extensive operations (or node-sharing) of class @code{List}. They behave similarly to the @code{slist} and similar classes described by Stroustrup.@refill All list nodes are created dynamically. Assignment is performed via copying. Class @code{DLList} supports all @code{SLList} operations, plus additional operations described below. For purposes of illustration, assume the specification of class @code{intSLList}. In addition to the operations listed here, SLLists support traversal via Pixes. @table @code @item intSLList a; Declares a to be an empty list. @item intSLList b = a; Sets b to an element-by-element copy of a. @item a.empty() returns true if a contains no elements @item a.length(); returns the number of elements in a. @item a.prepend(x); places x at the front of the list. @item a.append(x); places x at the end of the list. @item a.join(b) places all nodes from b to the end of a, simultaneously destroying b. @item x = a.front() returns a reference to the item stored at the head of the list, or triggers an error if the list is empty. @item a.rear() returns a reference to the rear of the list, or triggers an error if the list is empty. @item x = a.remove_front() deletes and returns the item stored at the head of the list. @item a.del_front() deletes the first element, without returning it. @item a.clear() deletes all items from the list. @item a.ins_after(Pix i, item); inserts item after position i. If i is null, insertion is at the front. @item a.del_after(Pix i); deletes the element following i. If i is 0, the first item is deleted. @end table @section Doubly linked lists Class @code{DLList} supports the following additional operations, as well as backward traversal via Pixes. @table @code @item x = a.remove_rear(); deletes and returns the item stored at the rear of the list. @item a.del_rear(); deletes the last element, without returning it. @item a.ins_before(Pix i, x) inserts x before the i. @item a.del(Pix& iint dir = 1) deletes the item at the current position, then advances forward if dir is positive, else backward. @end table @node Vector, Plex, LinkList, Top @chapter Vector classes Files @file{g++-include/Vec.[h, cc]P} and @file{g++-include/AVec.[h, cc]P} provide pseudo-generic standard array-based vector operations. Class @code{Vec} provides operations suitable for any base class that includes an equality operator. Subclass @code{AVec} provides additional arithmetic operations suitable for base classes that include the full complement of arithmetic operators. @code{Vecs} are constructed and assigned by copying. Thus, they should normally be passed by reference in applications programs. Several mapping functions are provided that allow programmers to specify operations on vectors as a whole. For illustrative purposes assume that classes @code{intVec} and @code{intAVec} have been generated via @code{genclass}. @section Constructors and assignment @table @code @item intVec a; declares a to be an empty vector. Its size may be changed via resize. @item intVec a(10); declares a to be an uninitialized vector of ten elements (numbered 0-9). @item intVec b(6, 0); declares b to be a vector of six elements, all initialized to zero. Any value can be used as the initial fill argument. @item a = b; Copies b to a. a is resized to be the same as b. @item a = b.at(2, 4) constructs a from the 4 elements of b starting at b[2]. @end table Assume declarations of @code{intVec a, b, c} and @code{int i, x} in the following. @section Status and access @table @code @item a.capacity(); returns the number of elements that can be held in a. @item a.resize(20); sets a's length to 20. All elements are unchanged, except that if the new size is smaller than the original, than trailing elements are deleted, and if greater, trailing elements are uninitialized. @item a[i]; returns a reference to the i'th element of a, or produces an error if i is out of range. @item a.elem(i) returns a reference to the i'th element of a. Unlike the @code{[]} operator, i is not checked to ensure that it is within range. @item a == b; returns true if a and b contain the same elements in the same order. @item a != b; is the converse of a == b. @end table @section Constructive operations @table @code @item c = concat(a, b); sets c to the new vector constructed from all of the elements of a followed by all of b. @item c = map(f, a); sets c to the new vector constructed by applying int function f(int) to each element of a. @item c = merge(a, b, f); sets c to the new vector constructed by merging the elements of ordered vectors a and b using ordering (comparison) function f. @item c = combine(f, a, b); sets c to the new vector constructed by applying int function f(int, int) to successive pairs of a and b. The result has length the shorter of a and b. @item c = reverse(a) sets c to a, with elements in reverse order. @end table @section Destructive operations @table @code @item a.reverse(); reverses a in-place. @item a.sort(f) sorts a in-place using comparison function f. The sorting method is a variation of the quicksort functions supplied with GNU emacs. @item a.fill(0, 4, 2) fills the 2 elements starting at a[4] with zero. @end table @section Other operations @table @code @item a.apply(f) applies function f to each element in a. @item x = a.reduce(f, base) accumulates the results of applying function f to successive elements of a starting with base. @item a.index(int targ); returns the index of the leftmost occurrence of the target, or -1, if it does not occur. @item a.error(char* msg) invokes the error handler. The default version prints the error message, then aborts. @end table @section AVec operations. AVecs provide additional arithmetic operations. All vector-by-vector operators generate an error if the vectors are not the same length. The following operations are provided, for @code{AVecs a, b} and base element (scalar) @code{s}. @table @code @item a = b; Copies b to a. a and b must be the same size. @item a = s; fills all elements of a with the value s. a is not resized. @item a + s; a - s; a * s; a / s adds, subtracts, multiplies, or divides each element of a with the scalar. @item a += s; a -= s; a *= s; a /= s; adds, subtracts, multiplies, or divides the scalar into a. @item a + b; a - b; product(a, b), quotient(a, b) adds, subtracts, multiplies, or divides corresponding elements of a and b. @item a += b; a -= b; a.product(b); a.quotient(b); adds, subtracts, multiplies, or divides corresponding elements of b into a. @item s = a * b; returns the inner (dot) product of a and b. @item x = a.sum(); returns the sum of elements of a. @item x = a.sumsq(); returns the sum of squared elements of a. @item x = a.min(); returns the minimum element of a. @item x = a.max(); returns the maximum element of a. @item i = a.min_index(); returns the index of the minimum element of a. @item i = a.max_index(); returns the index of the maximum element of a. Note that it is possible to apply vector versions other arithmetic operators via the mapping functions. For example, to set vector b to the cosines of doubleVec a, use @code{b = map(cos, a);}. This is often more efficient than performing the operations in an element-by-element fashion. @end table @node Plex, Stack, Vector, Top @chapter Plex classes A ``Plex'' is a kind of array with the following properties: @itemize @bullet @item Plexes may have arbitrary upper and lower index bounds. For example a Plex may be declared to run from indices -10 .. 10. @item Plexes may be dynamically expanded at both the lower and upper bounds of the array in steps of one element. @item Only elements that have been specifically initialized or added may be accessed. @item Elements may be accessed via indices. Indices are always checked for validity at run time. Plexes may be traversed via simple variations of standard array indexing loops. @item Plex elements may be accessed and traversed via Pixes. @item Plex-to-Plex assignment and related operations on entire Plexes are supported. @item Plex classes contain methods to help programmers check the validity of indexing and pointer operations. @item Plexes form ``natural'' base classes for many restricted-access data structures relying on logically contiguous indices, such as array-based stacks and queues. @item Plexes are implemented as pseudo-generic classes, and must be generated via the @code{genclass} utility. @end itemize Four subclasses of Plexes are supported: A @code{FPlex} is a Plex that may only grow or shrink within declared bounds; an @code{XPlex} may dynamically grow or shrink without bounds; an @code{RPlex} is the same as an @code{XPlex} but better supports indexing with poor locality of reference; a @code{MPlex} may grow or shrink, and additionally allows the logical deletion and restoration of elements. Because these classes are virtual subclasses of the ``abstract'' class @code{Plex}, it is possible to write user code such as @code{void f(Plex& a) ...} that operates on any kind of Plex. However, as with nearly any virtual class, specifying the particular Plex class being used results in more efficient code. Plexes are implemented as a linked list of @code{IChunks}. Each chunk contains a part of the array. Chunk sizes may be specified within Plex constructors. Default versions also exist, that use a @code{#define'd} default. Plexes grow by filling unused space in existing chunks, if possible, else, except for FPlexes, by adding another chunk. Whenever Plexes grow by a new chunk, the default element constructors (i.e., those which take no arguments) for all chunk elements are called at once. When Plexes shrink, destructors for the elements are not called until an entire chunk is freed. For this reason, Plexes (like C++ arrays) should only be used for elements with default constructors and destructors that have no side effects. Plexes may be indexed and used like arrays, although traversal syntax is slightly different. Even though Plexes maintain elements in lists of chunks, they are implemented so that iteration and other constructs that maintain locality of reference require very little overhead over that for simple array traversal Pix-based traversal is also supported. For example, for a plex, p, of ints, the following traversal methods could be used. @example for (int i = p.low(); i < p.fence(); p.next(i)) use(p[i]); for (int i = p.high(); i > p.ecnef(); p.prev(i)) use(p[i]); for (Pix t = p.first(); t != 0; p.next(t)) use(p(i)); for (Pix t = p.last(); t != 0; p.prev(t)) use(p(i)); @end example Except for MPlexes, simply using @code{++i} and @code{--i} works just as well as @code{p.next(i)} and @code{p.prev(i)} when traversing by index. Index-based traversal is generally a bit faster than Pix-based traversal. @code{XPlexes} and @code{MPlexes} are less than optimal for applications in which widely scattered elements are indexed, as might occur when using Plexes as hash tables or ``manually'' allocated linked lists. In such applications, @code{RPlexes} are often preferable. @code{RPlexes} use a secondary chunk index table that requires slightly greater, but entirely uniform overhead per index operation. Even though they may grow in either direction, Plexes are normally constructed so that their ``natural'' growth direction is upwards, in that default chunk construction leaves free space, if present, at the end of the plex. However, if the chunksize arguments to constructors are negative, they leave space at the beginning. All versions of Plexes support the following basic capabilities. (letting @code{Plex} stand for the type name constructed via the genclass utility (e.g., @code{intPlex}, @code{doublePlex})). Assume declarations of @code{Plex p, q}, @code{int i, j}, base element @code{x}, and Pix @code{pix}. @table @code @item Plex p; Declares p to be an initially zero-sized Plex with low index of zero, and the default chunk size. For FPlexes, chunk sizes represent maximum sizes. @item Plex p(int size); Declares p to be an initially zero-sized Plex with low index of zero, and the indicated chunk size. If size is negative, then the Plex is created with free space at the beginning of the Plex, allowing more efficient add_low() operations. Otherwise, it leaves space at the end. @item Plex p(int low, int size); Declares p to be an initially zero-sized Plex with low index of low, and the indicated chunk size. @item Plex p(int low, int high, Base initval, int size = 0); Declares p to be a Plex with indices from low to high, initially filled with initval, and the indicated chunk size if specified, else the default or (high - low + 1), whichever is greater. @item Plex q(p); Declares q to be a copy of p. @item p = q; Copies Plex q into p, deleting its previous contents. @item p.length() Returns the number of elements in the Plex. @item p.empty() Returns true if Plex p contains no elements. @item p.full() Returns true if Plex p cannot be expanded. This always returns false for XPlexes and MPlexes. @item p[i] Returns a reference to the i'th element of p. An exception (error) occurs if i is not a valid index. @item p.valid(i) Returns true if i is a valid index into Plex p. @item p.low(); p.high(); Return the minimum (maximum) valid index of the Plex, or the high (low) fence if the plex is empty. @item p.ecnef(); p.fence(); Return the index one position past the minimum (maximum) valid index. @item p.next(i); i = p.prev(i); Set i to the next (previous) index. This index may not be within bounds. @item p(pix) returns a reference to the item at Pix pix. @item pix = p.first(); pix = p.last(); Return the minimum (maximum) valid Pix of the Plex, or 0 if the plex is empty. @item p.next(pix); p.prev(pix); set pix to the next (previous) Pix, or 0 if there is none. @item p.owns(pix) Returns true if the Plex contains the element associated with pix. @item p.Pix_to_index(pix) If pix is a valid Pix to an element of the Plex, returns its corresponding index, else raises an exception. @item ptr = p.index_to_Pix(i) if i is a valid index, returns a the corresponding Pix. @item p.low_element(); p.high_element(); Return a reference to the element at the minimum (maximum) valid index. An exception occurs if the Plex is empty. @item p.can_add_low(); p.can_add_high(); Returns true if the plex can be extended one element downward (upward). These always return true for XPlex and MPlex. @item j = p.add_low(x); j = p.add_high(x); Extend the Plex by one element downward (upward). The new minimum (maximum) index is returned. @item j = p.del_low(); j = p.del_high() Shrink the Plex by one element on the low (high) end. The new minimum (maximum) element is returned. An exception occurs if the Plex is empty. @item p.append(q); Append all of Plex q to the high side of p. @item p.prepend(q); Prepend all of q to the low side of p. @item p.clear() Delete all elements, resetting p to a zero-sized Plex. @item p.reset_low(i); Resets p to be indexed starting at low() = i. For example. if p were initially declared via @code{Plex p(0, 10, 0)}, and then re-indexed via @code{p.reset_low(5)}, it could then be indexed from indices 5 .. 14. @item p.fill(x) sets all p[i] to x. @item p.fill(x, lo, hi) sets all of p[i] from lo to hi, inclusive, to x. @item p.reverse() reverses p in-place. @item p.chunk_size() returns the chunk size used for the plex. @item p.error(const char * msg) calls the resettable error handler. @end table MPlexes are plexes with bitmaps that allow items to be logically deleted and restored. They behave like other plexes, but also support the following additional and modified capabilities: @table @code @item p.del(i); p.del(pix) logically deletes p[i] (p(pix)). After deletion, attempts to access p[i] generate a error. Indexing via low(), high(), prev(), and next() skip the element. Deleting an element never changes the logical bounds of the plex. @item p.undel(i); p.undel(pix) logically undeletes p[i] (p(pix)). @item p.del_low(); p.del_high() Delete the lowest (highest) undeleted element, resetting the logical bounds of the plex to the next lowest (highest) undeleted index. Thus, MPlex del_low() and del_high() may shrink the bounds of the plex by more than one index. @item p.adjust_bounds() Resets the low and high bounds of the Plex to the indexes of the lowest and highest actual undeleted elements. @item int i = p.add(x) Adds x in an unused index, if possible, else performs add_high. @item p.count() returns the number of valid (undeleted) elements. @item p.available() returns the number of available (deleted) indices. @item int i = p.unused_index() returns the index of some deleted element, if one exists, else triggers an error. An unused element may be reused via undel. @item pix = p.unused_Pix() returns the pix of some deleted element, if one exists, else 0. An unused element may be reused via undel. @end table @node Stack, Queue, Plex, Top @chapter Stacks Stacks are declared as an ``abstract'' class. They are currently implemented in any of three ways. @table @code @item VStack implement fixed sized stacks via arrays. @item XPStack implement dynamically-sized stacks via XPlexes. @item SLStack implement dynamically-size stacks via linked lists. @end table All possess the same capabilities. They differ only in constructors. VStack constructors require a fixed maximum capacity argument. XPStack constructors optionally take a chunk size argument. SLStack constructors take no argument. Assume the declaration of a base element @code{x}. @table @code @item Stack s; or Stack s(int capacity) declares a Stack. @item s.empty() returns true if stack s is empty. @item s.full() returns true if stack s is full. XPStacks and SLStacks never become full. @item s.length() returns the current number of elements in the stack. @item s.push(x) pushes x on stack s. @item x = s.pop() pops and returns the top of stack @item s.top() returns a reference to the top of stack. @item s.del_top() pops, but does not return the top of stack. When large items are held on the stack it is often a good idea to use @code{top()} to inspect and use the top of stack, followed by a @code{del_top()} @item s.clear() removes all elements from the stack. @end table @node Queue, Deque, Stack, Top @chapter Queues Queues are declared as an ``abstract'' class. They are currently implemented in any of three ways. @table @code @item VQueue implement fixed sized Queues via arrays. @item XPQueue implement dynamically-sized Queues via XPlexes. @item SLQueue implement dynamically-size Queues via linked lists. @end table All possess the same capabilities. They differ only in constructors. VQueue constructors require a fixed maximum capacity argument. XPQueue constructors optionally take a chunk size argument. SLQueue constructors take no argument. Assume the declaration of a base element @code{x}. @table @code @item Queue q; or Queue q(int capacity); declares a queue. @item q.empty() returns true if queue q is empty. @item q.full() returns true if queue q is full. XPQueues and SLQueues are never full. @item q.length() returns the current number of elements in the queue. @item q.enq(x) enqueues x on queue q. @item x = q.deq() dequeues and returns the front of queue @item q.front() returns a reference to the front of queue. @item q.del_front() dequeues, but does not return the front of queue @item q.clear() removes all elements from the queue. @end table @node Deque, Set, Queue, Top @chapter Double ended Queues Deques are declared as an ``abstract'' class. They are currently implemented in two ways. @table @code @item XPDeque implement dynamically-sized Deques via XPlexes. @item DLDeque implement dynamically-size Deques via linked lists. @end table All possess the same capabilities. They differ only in constructors. XPDeque constructors optionally take a chunk size argument. DLDeque constructors take no argument. Double-ended queues support both stack-like and queue-like capabilities: Assume the declaration of a base element @code{x}. @table @code @item Deque d; or Deque d(int initial_capacity) declares a deque. @item d.empty() returns true if deque d is empty. @item d.length() returns the current number of elements in the deque. @item d.enq(x) inserts x at the rear of deque d. @item d.push(x) inserts x at the front of deque d. @item x = d.deq() dequeues and returns the front of deque @item d.front() returns a reference to the front of deque. @item d.rear() returns a reference to the rear of the deque. @item d.del_front() deletes, but does not return the front of deque @item d.del_rear() deletes, but does not return the rear of the deque. @item d.clear() removes all elements from the deque. @end table @node PQ, Set, Deque, Top @chapter Priority Queue class prototypes. Priority queues maintain collections of objects arranged for fast access to the least element. Several prototype implementations of priority queues are supported. @table @code @item XPPQs implement 2-ary heaps via XPlexes. @item SplayPQs implement PQs via Sleater and Tarjan's (JACM 1985) splay trees. The algorithms use a version of ``simple top-down splaying'' (described on page 669 of the article). The simple-splay mechanism for priority queue functions is loosely based on the one used by D. Jones in the C splay tree functions available from volume 14 of the uunet.uu.net archives. @item PHPQs implement pairing heaps as described by Fredman and Sedgewick @emph{Algorithmica}, Vol 1, p111-129. Storage for heap elements is managed via an internal freelist technique. The constructor allows an initial capacity estimate for freelist space. The storage is automatically expanded if necessary to hold new items. The deletion technique is a fast ``lazy deletion'' strategy that marks items as deleted, without reclaiming space until the items come to the top of the heap. @end table All PQ classes support the following operations, for some PQ class @code{Heap}, instance @code{h}, @code{Pix ind}, and base class variable @code{x}. @table @code @item h.empty() returns true if there are no elements in the PQ. @item h.length() returns the number of elements in h. @item ind = h.enq(x) Places x in the PQ, and returns its index. @item x = h.deq() Dequeues the minimum element of the PQ into x, or generates an error if the PQ is empty. @item h.front() returns a reference to the minimum element. @item h.del_front() deletes the minimum element. @item h.clear(); deletes all elements from h; @item h.contains(x) returns true if x is in h. @item h(ind) returns a reference to the item indexed by ind. @item ind = h.first() returns the Pix of first item in the PQ or 0 if empty. This need not be the Pix of the least element. @item h.next(ind) advances ind to the Pix of next element, or 0 if there are no more. @item ind = h.seek(x) Sets ind to the Pix of x, or 0 if x is not in h. @item h.del(ind) deletes the item with Pix ind. @end table @node Set, Bag, PQ, Top @chapter Set class prototypes Set classes maintain unbounded collections of items containing no duplicate elements. These are currently implemented in several ways. @table @code @item XPSets implement unordered sets via XPlexes. @item OXPSets implement ordered sets via XPlexes. @item SLSets implement unordered sets via linked lists @item OSLSets implement ordered sets via linked lists @item AVLSets implement ordered sets via threaded AVL trees @item BSTSets implement ordered sets via binary search trees. The trees may be manually rebalanced via the @code{balance()} member function. @item SplaySets implement ordered sets via Sleater and Tarjan's (JACM 1985) splay trees. The algorithms use a version of ``simple top-down splaying'' (described on page 669 of the article). @item VHSets implement unordered sets via hash tables. The tables are automatically resized when their capacity is exhausted. @item VOHSets implement unordered sets via ordered hash tables The tables are automatically resized when their capacity is exhausted. @item CHSets implement unordered sets via chained hash tables. @end table The different implementations differ in whether their constructors require an argument specifying their initial capacity. Initial capacities are required for plex and hash table based Sets. If none is given @code{DEFAULT_INITIAL_CAPACITY} (from @file{defs.h}) is used.@refill Sets support the following operations, for some class @code{Set}, instances @code{a} and @code{b}, @code{Pix ind}, and base element @code{x}. Since all implementations are virtual derived classes of the @code{Set} class, it is possible to mix and match operations across different implementations, although, as usual, operations are generally faster when the particular classes are specified in functions operating on Sets. @table @code @item Set a; or Set a(int initial_size); Declares a to be an empty Set. The second version is allowed in set classes that require initial capacity or sizing specifications. @item a.empty() returns true if a is empty. @item a.length() returns the number of elements in a. @item Pix ind = a.add(x) inserts x into a, returning its index. @item a.del(x) deletes x from a. @item a.clear() deletes all elements from a; @item a.contains(x) returns true if x is in a. @item a(ind) returns a reference to the item indexed by ind. @item ind = a.first() returns the Pix of first item in the set or 0 if the Set is empty. For ordered Sets, this is the Pix of the least element. @item a.next(ind) advances ind to the Pix of next element, or 0 if there are no more. @item ind = a.seek(x) Sets ind to the Pix of x, or 0 if x is not in a. @item a == b returns true if a and b contain all the same elements. @item a != b returns true if a and b do not contain all the same elements. @item a <= b returns true if a is a subset of b. @item a |= b Adds all elements of b to a. @item a -= b Deletes all elements of b from a. @item a &= b Deletes all elements of a not occurring in b. @end table @node Bag, Map, Set, Top @chapter Bag class prototypes Bag classes maintain unbounded collections of items potentially containing duplicate elements. These are currently implemented in several ways. @table @code @item XPBags implement unordered Bags via XPlexes. @item OXPBags implement ordered Bags via XPlexes. @item SLBags implement unordered Bags via linked lists @item OSLBags implement ordered Bags via linked lists @item SplayBags implement ordered Bags via Sleater and Tarjan's (JACM 1985) splay trees. The algorithms use a version of ``simple top-down splaying'' (described on page 669 of the article). @item VHBags implement unordered Bags via hash tables. The tables are automatically resized when their capacity is exhausted. @item CHBags implement unordered Bags via chained hash tables. @end table The different implementations differ in whether their constructors require an argument specifying their initial capacity. Initial capacities are required for plex and hash table based Bags. If none is given @code{DEFAULT_INITIAL_CAPACITY} (from @file{defs.h}) is used.@refill Bags support the following operations, for some class @code{Bag}, instances @code{a} and @code{b}, @code{Pix ind}, and base element @code{x}. Since all implementations are virtual derived classes of the @code{Bag} class, it is possible to mix and match operations across different implementations, although, as usual, operations are generally faster when the particular classes are specified in functions operating on Bags. @table @code @item Bag a; or Bag a(int initial_size) Declares a to be an empty Bag. The second version is allowed in Bag classes that require initial capacity or sizing specifications. @item a.empty() returns true if a is empty. @item a.length() returns the number of elements in a. @item ind = a.add(x) inserts x into a, returning its index. @item a.del(x) deletes one occurrence of x from a. @item a.remove(x) deletes all occurrences of x from a. @item a.clear() deletes all elements from a; @item a.contains(x) returns true if x is in a. @item a.nof(x) returns the number of occurrences of x in a. @item a(ind) returns a reference to the item indexed by ind. @item int = a.first() returns the Pix of first item in the Bag or 0 if the Bag is empty. For ordered Bags, this is the Pix of the least element. @item a.next(ind) advances ind to the Pix of next element, or 0 if there are no more. @item ind = a.seek(x. Pix from = 0) Sets ind to the Pix of the next occurrence x, or 0 if there are none. If from is 0, the first occurrence is returned, else the following from. @end table @node Map, GetOpt, Bag, Top @chapter Map (Associative array) class prototypes. Maps support associative array operations (insertion, deletion, and membership of records based on an associated key). They require the specification of two types, the key type and the contents type. These are currently implemented in several ways. @table @code @item AVLMaps implement ordered Maps via threaded AVL trees @item RAVLMaps Similar, but also maintain ranking information, used via @code{ranktoPix(int r)}, that returns the @code{Pix} of the item at rank r, and @code{rank(key)} that returns the rank of the corresponding item. @item SplayMaps implement ordered Maps via Sleater and Tarjan's (JACM 1985) splay trees. The algorithms use a version of ``simple top-down splaying'' (described on page 669 of the article). @item VHMaps implement unordered Maps via hash tables. The tables are automatically resized when their capacity is exhausted. @item CHMaps implement unordered Maps via chained hash tables. @end table The different implementations differ in whether their constructors require an argument specifying their initial capacity. Initial capacities are required for plex and hash table based Maps. If none is given @code{DEFAULT_INITIAL_CAPACITY} (from @file{defs.h}) is used.@refill All Map classes share the following operations (for some Map class, @code{Map} instance @code{d}, @code{Pix ind} and key variable @code{k}, and contents variable @code{x}). @table @code @item Map d(x); Map d(x, int initial_capacity) Declare d to be an empty Map. The required argument, x, specifies the default contents, i.e., the contents of an otherwise uninitialized location. The second version, specifying initial capacity is allowed for Maps with an initial capacity argument. @item d.empty() returns true if d contains no items. @item d.count() returns the number of items in d. @item d[k] returns a reference to the contents of item with key k. If no such item exists, it is installed with the default contents. Thus d[k] = x installs x, and x = d[k] retrieves it. @item d.contains(k) returns true if an item with key field k exists in d. @item d.del(k) deletes the item with key k. @item d.clear() deletes all items from the table. @item x = d.dflt() returns the default contents. @item k = d.key(ind) returns a reference to the key at Pix ind. @item x = d.contents(ind) returns a reference to the contents at Pix ind. @item ind = d.first() returns the Pix of the first element in d, or 0 if d is empty. @item d.next(ind) advances ind to the next element, or 0 if there are no more. @item ind = d.seek(k) returns the Pix of element with key k, or 0 if k is not in d. @end table @node GetOpt, Gperf, Map, Top @chapter C++ version of the GNU/UNIX getopt function The GetOpt class provides an efficient and structured mechanism for processing command-line options from an application program. The sample program fragment below illustrates a typical use of the GetOpt class for some hypothetical application program: @example #include #include //... int debug_flag, compile_flag, size_in_bytes; int main (int argc, char **argv) @{ // Invokes ctor `GetOpt (int argc, char **argv, char *optstring);' GetOpt getopt (argc, argv, "dcs:"); int option_char; // Invokes member function `int operator ()(void);' while ((option_char = getopt ()) != EOF) switch (option_char) @{ case 'd': debug_flag = 1; break; case 'c': compile_flag = 1; break; case 's': size_in_bytes = atoi (getopt.optarg); break; case '?': fprintf (stderr, "usage: %s [dcs]\n", argv[0]); @} @} @end example Unlike the C library version, the libg++ GetOpt class uses its constructor to initialize class data members containing the argument count, argument vector, and the option string. This simplifies the interface for each subsequent call to member function @code{int operator ()(void)}. The C version, on the other hand, uses hidden static variables to retain the option string and argument list values between calls to @code{getopt}. This complicates the @code{getopt} interface since the argument count, argument vector, and option string must be passed as parameters for each invocation. For the C version, the loop in the previous example becomes: @example while ((option_char = getopt (argc, argv, "dcs:")) != EOF) // ... @end example which requires extra overhead to pass the parameters for every call. Along with the GetOpt constructor and @code{int operator ()(void)}, the other relevant elements of class GetOpt are: @table @code @item char *optarg Used for communication from @code{operator ()(void)} to the caller. When @code{operator ()(void)} finds an option that takes an argument, the argument value is stored here. @item int optind Index in @code{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 @code{operator ()(void)}. When @code{operator ()(void)} returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, @code{optind} communicates from one call to the next how much of @code{argv} has been scanned so far. @end table The libg++ version of GetOpt acts like standard UNIX @code{getopt} for the calling routine, 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 @code{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 _POSIX_OPTION_ORDER disables permutation. Then the behavior is completely standard. @node Gperf, Projects, GetOpt, Top @chapter A Perfect Hash Function Generator GNU GPERF is a utility program that automatically generates perfect hash functions from a list of keywords. The GNU C, GNU C++, GNU Pascal, GNU Modula 3 compilers and the GNU indent code formatting program all utilize reserved word recognizer routines generated by GPERF. Complete documentation and source code is available in the ./gperf subdirectory in the libg++ distribution. A paper describing GPERF in detail is available in the proceedings of the USENIX Second C++ Conference. @node Projects, Top, Gperf, Top @chapter Projects and other things left to do @section Coming Attractions Some things that will probably be available in libg++ in the near future: @itemize @bullet @item Revamped C-compatibility header files that will be compatible with the forthcoming (ANSI-based) GNU libc.a @item A revision of the File-based classes that will use the GNU stdio library, and also be 100% compatible (even at the streambuf level) with the AT&T 2.0 stream classes. @item Additional container class prototypes. @item generic Matrix class prototypes. @item A task package probably based on Dirk Grunwald's threads package. @end itemize @section Wish List Some things that people have mentioned that they would like to see in libg++, but for which there have not been any offers: @itemize @bullet @item Class-based interfaces to Sun RPC using g++ wrappers. @item A method to automatically convert or incorporate libg++ classes so they can be used directly in Gorlen's OOPS environment. @item A class browser. @item A better general exception-handling strategy. @item Better documentation. @end itemize @section How to contribute Programmers who have written C++ classes that they believe to be of general interest are encourage to write to dl at rocky.oswego.edu. Contributing code is not difficult. Here are some general guidelines: @itemize @bullet @item FSF must maintain the right to accept or reject potential contributions. Generally, the only reasons for rejecting contributions are cases where they duplicate existing or nearly-released code, contain unremovable specific machine dependencies, or are somehow incompatible with the rest of the library. @item Acceptance of contributions means that the code is accepted for adaptation into libg++. FSF must reserve the right to make various editorial changes in code. Very often, this merely entails formatting, maintenance of various conventions, etc. Contributors are always given authorship credit and shown the final version for approval. @item Contributors must assign their copyright to FSF via a form sent out upon acceptance. Assigning copyright to FSF ensures that the code may be freely distributed. @item Assistance in providing documentation, test files, and debugging support is strongly encouraged. @end itemize Extensions, comments, and suggested modifications of existing libg++ features are also very welcome. @contents @bye conventions, etc. Contributors are always given authorship credit and shown the final version for approval. @item Contributors must assign their copyright to FSF via a form sent out upon acceptance. Assigning copyright to FSF ensures that the code may be freely distributed. @item Assistance in providing documentation, test files, and debugging support is strongly encouraged. @end itemlibg++/etc/fib.cc 600 473 0 32273 4677677777 7031 #include #include // Fun and games with the Fibonacci function. // Also demonstrates use of the `named return value' extension. // fib1 and fib2 from Doug Lea, others from Doug Schmidt. /**********************************************************************/ // Standard iterative version: // Schmidt uses convention that fib(0) = 1, not fib(0) = 0; // so I just increment n here. Integer fib1(int n) { ++n; if (n <= 0) return 0; else { Integer f = 1; Integer prev = 0; while (n > 1) { Integer tmp = f; f += prev; prev = tmp; --n; } return f; } } /**********************************************************************/ // n // via transformed matrix multiplication of ( 0 1 ) // ( 1 1 ) // simplified knowing that the matrix is always of // the form (a b) // (b c) // (where (a, b) and (b, c) are conseq pairs of conseq fib's; // further simplified by realizing that c = a+b, so c is only // calculated implicitly. // Given all this, do the power via the standard russian // peasant divide-and-conquer algorithm, with // the current multiplier held in (p q) // (q -) // // This example also shows that using procedure calls instead of operators // can be faster for Integers // operator version Integer fib2(int n) { ++n; // 1-based for compatability; see above Integer a = 0; if (n <= 0) return a; else { Integer b = 1; Integer p = 0; Integer q = 1; for(;;) { if (n == 1) return a * p + b * q; else if (odd (n)) { Integer aq = a * q; Integer bq = b * q; a = a * p + bq; b = b * p + aq + bq; } Integer qq = q * q; q = (q * p) * 2 + qq; p = (p * p) + qq; n >>= 1; } } } // with all expressions named, including return value Integer fib2a(int n) return a(0) { ++n; if (n <= 0) return; else { Integer b = 1; Integer p = 0; Integer q = 1; for(;;) { if (n == 1) { Integer bq = b * q; a *= p ; a += bq; return; } else if (odd (n)) { Integer aq = a * q; Integer bq = b * q; a *= p; a += bq; b *= p; b += bq; b += aq; } Integer qq = q * q; Integer pp = p * p; Integer pq = p * q; q = pq; q += pq; q += qq; p = pp; p += qq; n >>= 1; } } } // procedure call version Integer fib2b(int n) return a(0) { ++n; if (n <= 0) return; else { Integer b = 1; Integer p = 0; Integer q = 1; for(;;) { if (n == 1) { Integer bq; mul(b, q, bq); mul(a, p, a); add(a, bq, a); return; } else if (odd (n)) { Integer aq; mul(a, q, aq); Integer bq; mul(b, q, bq); mul(a, p, a); mul(b, p, b); add(a, bq, a); add(b, bq, b); add(b, aq, b); } Integer qq; mul(q, q, qq); Integer pp; mul(p, p, pp); Integer pq; mul(p, q, pq); add(pq, pq, q); add(q, qq, q); add(pp, qq, p); n >>= 1; } } } // procedure call version, reusing variables Integer fib2c(int n) return a(0) { ++n; if (n <= 0) return; else { Integer b = 1; Integer p = 0; Integer q = 1; Integer bq, aq, qq, pp, pq; for(;;) { if (n == 1) { mul(b, q, bq); mul(a, p, a); add(a, bq, a); return; } else if (odd (n)) { mul(a, q, aq); mul(b, q, bq); mul(a, p, a); mul(b, p, b); add(a, bq, a); add(b, bq, b); add(b, aq, b); } mul(q, q, qq); mul(p, p, pp); mul(p, q, pq); add(pq, pq, q); add(q, qq, q); add(pp, qq, p); n >>= 1; } } } /**********************************************************************/ // Ullman memoizers: class Ullman_Array { // Ullman's array implementation allows Initialization, Store, and Fetch // in O(1) time. Although it takes O(n) space the time to initialize enables // us to compute a Fibonacci number in O(log n) time! // The basic concept of Ullman's array implementation is the use of a // Hand_Shake_Array and an Index_Array. An Index location in the array is // only considered initialized if the contents in the Hand_Shake_Array and // Index_Array point to each other, i.e. they ``shake hands!'' private: int max_array_range; int max_set_size; int *index_array; int *hand_shake_array; Integer *storage_array; int current_max; public: Integer uninitialized; Ullman_Array (int array_range, int set_size); void store (int index, Integer &item); Integer fetch (int index); }; inline Ullman_Array::Ullman_Array (int array_range, int set_size) { max_array_range = array_range; max_set_size = set_size; index_array = new int[max_array_range + 1]; hand_shake_array = new int[max_set_size]; storage_array = new Integer[max_set_size]; current_max = -1; uninitialized = 0; // No fibonacci number has value of 0. } // Store Item at the proper Index of the Ullman array. // The Hand_Shake_Array determines whether the Index has already // been stored into. If it has NOT, then a new location for it // is set up in the Storage_Array and the Hand_Shake_Array and Index_Array // are set to point at each other. inline void Ullman_Array::store (int index, Integer &item) { int hand_shake_index = index_array[index]; if (hand_shake_index > current_max || hand_shake_index < 0 || index != hand_shake_array[hand_shake_index]) { hand_shake_index = ++current_max; hand_shake_array[hand_shake_index] = index; index_array[index] = hand_shake_index; } storage_array[hand_shake_index] = item; } // Returns uninitialized if not initialized, else returns Item at Index. inline Integer Ullman_Array::fetch(int index) { int hand_shake_index = index_array[index]; if (hand_shake_index > current_max || hand_shake_index < 0 || index != hand_shake_array[hand_shake_index]) return uninitialized; else return storage_array[hand_shake_index]; } /**********************************************************************/ class Memo_Fib : public Ullman_Array { public: Memo_Fib (int fib_num); Integer fib3 (int n); Integer fib3a (int n); }; // The total number of Items computed by the Fib routine is bounded by // 4 * ceiling of log base 2 of Fib_Num. Of course, the basis of the // recurrence is Fib(0) == 1 and Fib(1) == 1! Memo_Fib::Memo_Fib (int fib_num): (fib_num, (4 * lg (fib_num))) { store (0, 1); store (1, 1); } // Uses the memoization technique to reduce the time complexity to calculate // the nth Fibonacci number in O(log n) time. If the value of ``n'' is // already in the table we return it in O(1) time. Otherwise, we use the // super-nifty divide-and-conquer algorithm to break the problem up into // 4 pieces of roughly size n/2 and solve them recursively. Although this // looks like an O(n^2) recurrence the memoization reduces the number of // recursive calls to O(log n)! Integer Memo_Fib::fib3 (int n) return fib (fetch (n)); { if (fib == uninitialized) { int m = n >> 1; fib = fib3 (m) * fib3 (n - m) + fib3 (m - 1) * fib3 (n - m - 1); store (n, fib); } } // The same, with procedure calls instead of operators Integer Memo_Fib::fib3a (int n) return fib (fetch (n)); { if (fib == uninitialized) { int m = n >> 1; Integer tmp; mul(fib3a(m), fib3a(n - m), fib); mul(fib3a(m - 1), fib3a(n - m - 1), tmp); add(fib, tmp, fib); store (n, fib); } } /**********************************************************************/ // Here's a linear-time dynamic programming solution to the same problem. // It makes use of G++/GCC dynamic arrays to build a table of ``n'' partial // solutions. Naturally, there is an O(1) space solution, but this O(n) // approach is somewhat more intuitive and follows the ``original'' recurrence // more closely. Integer fib4 (int n) { Integer table[n + 1]; table[0] = 1; table[1] = 1; for (int i = 2; i <= n; i++) table[i] = table[i - 1] + table[i - 2]; return table[n]; } /**********************************************************************/ // The extended integers provide numbers of the form: // (base+sqrt(5)*Rad_5)/2^Pow_2 // These are used to find the solution to the closed form of fib(n). struct Extended_Int { Integer base; Integer rad_5; int pow_2; Extended_Int (Integer ¶m1, Integer ¶m2, int param3); Extended_Int (Extended_Int& param); Extended_Int (void) {} friend Extended_Int operator- (Extended_Int ¶m1, Extended_Int ¶m2); friend Extended_Int operator* (Extended_Int ¶m1, Extended_Int ¶m2); friend Extended_Int sqrt (Extended_Int ¶m1); friend Extended_Int pow (Extended_Int ¶m1, int num); }; inline Extended_Int::Extended_Int (Integer ¶m1, Integer ¶m2, int param3) { base = param1; rad_5 = param2; pow_2 = param3; } inline Extended_Int::Extended_Int (Extended_Int ¶m) { base = param.base; rad_5 = param.rad_5; pow_2 = param.pow_2; } inline Extended_Int operator- (Extended_Int ¶m1, Extended_Int ¶m2) return temp; { temp.base = param1.base - param2.base; temp.rad_5 = param1.rad_5 - param2.rad_5; temp.pow_2 = param1.pow_2; } Extended_Int operator* (Extended_Int ¶m1, Extended_Int ¶m2) return temp; { temp.base = param1.base * param2.base + 5 * param1.rad_5 * param2.rad_5; temp.rad_5 = param1.base * param2.rad_5 + param1.rad_5 * param2.base; temp.pow_2 = param1.pow_2 + param2.pow_2; while (temp.pow_2 > 0 && !(odd (temp.base) || odd (temp.rad_5))) { temp.base >>= 1; temp.rad_5 >>= 1; temp.pow_2--; } } inline Extended_Int sqrt (Extended_Int ¶m1) { return param1 * param1; } Extended_Int pow (Extended_Int ¶m1, int num) { if (num > 1) return odd (num) ? param1 * sqrt (pow (param1, num >> 1)) : sqrt (pow (param1, num >> 1)); else return param1; } /**********************************************************************/ // Calculates fib (n) by solving the closed form of the recurrence. class Closed_Form : private Extended_Int { private: Extended_Int cons1; Extended_Int cons2; public: Closed_Form (void): cons1 (1, 1, 1), cons2 (1, -1, 1) {} Integer fib5 (int n); }; Integer Closed_Form::fib5 (int num) { Extended_Int temp = pow (cons1, num + 1) - pow (cons2, num + 1); while (temp.pow_2 > 0 && !(odd (temp.base) || odd (temp.rad_5))) { temp.base >>= 1; temp.rad_5 >>= 1; temp.pow_2--; } return temp.rad_5; } /**********************************************************************/ static const int DEFAULT_SIZE = 10000; void dofib1(int fib_num) { start_timer (); Integer result = fib1 (fib_num); double time = return_elapsed_time(0.0); cout << "fib1 = " << result << ". Time = " << time << "\n"; } void dofib2(int fib_num) { start_timer (); Integer result = fib2 (fib_num); double time = return_elapsed_time(0.0); cout << "fib2 = " << result << ". Time = " << time << "\n"; } void dofib2a(int fib_num) { start_timer (); Integer result = fib2a(fib_num); double time = return_elapsed_time(0.0); cout << "fib2a = " << result << ". Time = " << time << "\n"; } void dofib2b(int fib_num) { start_timer (); Integer result = fib2b(fib_num); double time = return_elapsed_time(0.0); cout << "fib2b = " << result << ". Time = " << time << "\n"; } void dofib2c(int fib_num) { start_timer (); Integer result = fib2c(fib_num); double time = return_elapsed_time(0.0); cout << "fib2c = " << result << ". Time = " << time << "\n"; } void dofib3(int fib_num) { start_timer (); Memo_Fib Memo_Test (fib_num); Integer result = Memo_Test.fib3 (fib_num); double time = return_elapsed_time(0.0); cout << "fib3 = " << result << ". Time = " << time << "\n"; } void dofib3a(int fib_num) { start_timer (); Memo_Fib Memo_Test (fib_num); Integer result = Memo_Test.fib3a (fib_num); double time = return_elapsed_time(0.0); cout << "fib3a = " << result << ". Time = " << time << "\n"; } void dofib4(int fib_num) { start_timer (); Integer result = fib4 (fib_num); double time = return_elapsed_time(0.0); cout << "fib4 = " << result << ". Time = " << time << "\n"; } void dofib5(int fib_num) { Closed_Form Rec_Test; Integer result = Rec_Test.fib5 (fib_num); double time = return_elapsed_time(0.0); cout << "fib5 = " << result << ". Time = " << time << "\n"; } int main (int argc, char *argv[]) { int fib_num = (argc > 1) ? atoi (argv[1]) : DEFAULT_SIZE; cout << "Results for fib(" << fib_num << "):\n\n"; dofib1(fib_num); dofib2(fib_num); dofib2a(fib_num); dofib2b(fib_num); dofib2c(fib_num); dofib3(fib_num); dofib3a(fib_num); // dofib4(fib_num); // This uses too much mem for large n! dofib5(fib_num); return 0; } 5 (fib_num); double time = return_elapsed_time(0.0); cout << "fib5 = " << result << ". Time = " << time << "\n"; } int main (int argc, char *argv[]) { int fib_num = (argc > 1) ? atoi (argv[1]) : DEFAULT_SIZE; cout << "Results for fib(" << fib_num << "):\n\n"; dofib1(fib_num); dofib2(fib_num); dofiblibg++/etc/Makefile 600 473 0 11603 4677677777 7414 # A makefile for the stuff now in libg++/etc # ------ source locations # source directory for libg++.a SRCDIR = ../../src # source include directory SRCIDIR= ../../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< DEMOS= fib all: etags demos graph trie-gen ADT-examples benchmarks lf PlotFile3D tests demos: $(DEMOS) tests: $(DEMOS) -./fib 1000 # -./dhrystone etags: etags.o $(CC) $(CFLAGS) etags.o -o etags etags.o: etags.c $(CC) $(CFLAGS) -DETAGS -c etags.c fib: fib.o $(GXX) fib.o $(GXXLDFLAGS) -o fib generic-q: generic-q.o $(GXX) generic-q.o $(GXXLDFLAGS) -o generic-q tsort: tsortinp tsort.o $(GXX) tsort.o $(GXXLDFLAGS) -o tsort tsortinp: tsortinp.o $(GXX) tsortinp.o $(GXXLDFLAGS) -o tsortinp keyhash: keyhash.o $(GXX) keyhash.o $(GXXLDFLAGS) -o keyhash search: search.o $(GXX) search.o $(GXXLDFLAGS) -o search genkey: genPatkey.o $(GXX) genPatkey.o $(GXXLDFLAGS) -o genkey Patricia.o: Patricia.h Patmain.o: Patricia.h patricia: Patmain.o Patricia.o $(GXX) Patmain.o Patricia.o $(GXXLDFLAGS) -o patricia kmp: kmp.o $(GXX) kmp.o $(GXXLDFLAGS) -o kmp graph: always (cd graph; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") trie-gen: always (cd trie-gen; $(MAKE) test GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") ADT-examples: always (cd ADT-examples; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") benchmarks: always (cd benchmarks; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") PlotFile3D: always (cd PlotFile3D; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") lf: always (cd lf; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR="$(LIBDIR)" SRCIDIR="$(SRCIDIR)" CC="$(CC)" CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)" LDXX="$(LDXX)" GXXCRT1="$(GXXCRT1)" MAKE="$(MAKE)" prefix="$(prefix)") always: clean: rm -f *.o $(DEMOS) core input C++.hack* etags (cd graph; make realclean) (cd PlotFile3D; make clean) (cd trie-gen; make clean) (cd benchmarks; make clean) (cd ADT-examples; make clean) (cd lf; make realclean) E)" prefix="$(prefix)") lf: always (cd lf; $(MAKE) GXX="$(GXX)" GXXFLAGS="$(GXXFLAGS)" GXXLDFLAGS="$(GXXLDFLAGS)" LIBDIR=libg++/etc/release.log 600 473 0 30760 4677677777 10104 * changes from libg++-1.36.1 to libg++-1.36.3 * `Tmp' classes have been eliminated from Strings, Integers, etc. (Via some retuning of the main classes, Tmp classes were found to not significantly impact performance one way or the other, so they were removed.) * There is now a version of malloc, directly supporting operator new, etc. It may be faster and better suited to C++ applications than your libc malloc. You should be able to use it unless you need a special malloc for a distributed shared memory environment or the like. If you can't use it, edit the appropriate flag in the top-level Makefile. I would very much appreciate feedback about whether this malloc makes any difference in time or space efficiency than whatever you are now using. * By default, output is now line-buffered. Use the NO_LINE_BUFFER_STREAMBUF define in the Makefile to override * Otherwise, the stream classes remain C++-1.2 compatible. C++-2.0-compatible versions are still in the works. * various and sundry bug fixes, minor enhancements, and/or portability improvements as described in the ChangeLog. * changes from libg++-1.35.0 & 1.35.1 to 1.36.1 * various and sundry bug fixes, minor enhancements, and/or portability improvements as described in the ChangeLog. * Most everything should now work on most SystemV machines. Let me know if they don't. * genclass now allows an optional prefix to be used instead of type name concatenation in order to help minimize filename lengths for SYSV users. This is not a great solution, but is A solution to filename length problems for SYSV users. * Some, but not all classes now behave well with respect to the new 2.0 const specifications. Some uncertainties about how g++ will interpret gcc-based const function qualifiers (to indicate lack of side effects) versus C++-2.0 const member functions has held up the conversion of some classes to use const in either or both of these ways. * A version of etags suitable for use with c++ is in etc/ (courtesy of J. Clark) * `graph', a unix graph(1) work-alike is in libg++/etc, courtesy of Rich Murphey. * RAVLMap (Ranked AVLs) prototypes. * The GetOpt class & support has been moved from etc/ into libg++.a * Streams have been redone to be nearly 100% AT&T 1.2 compatible. One minor possible incompatibility exists (ostream<< char) that can be eliminated via #define NO_OUTPUT_CHAR at the top of stream.h. This is probably necessary in order to compile et++. See libg++.texinfo for more details. The new stream implementation is not particulary pretty. Its main virtue is that it avoids some of the worst things about both AT&T streams and old libg++ streams. A much superior AT&T 2.0-iostream superset is in the works for future release. * changes from libg++-1.25.0 to libg++-1.32.0 * Nearly all data and methods previously declared as `private' are now declared as `protected' to make subclassing from library classes easier. * Most classes now contain a method `OK()' that checks to make sure that an objects internal data is in a valid state. See the documentation for further details * Mosts tests in ./tests now contain various kinds of assert statements. If tests execute without assertion failures, and without any other errors that cause aborted execution, you may consider them successful. The test files now include nearly all of my internal tests, which in turn have been made more extensive. * Plex classes are available. A bit of propaganda about these: Plexes are very attractive replacements for arrays in many contexts. Try them! * `shrink' and `contains' have been added to Obstack * Files and streams have not yet been revamped (a complete reworking awaits the AT&T 2.0 stream specification), but have been adjusted to provide slightly faster IO in some cases, and now support the use of a user-supplied string to read or write from instead of an actual IO source. * Rationals are now normalized when input via `>>'. * atoI is fixed. * variable-length representations in String, Integer, etc., are now completely different. See the documentation for details. * New String functions: * readline -- read in a line from an istream as a String * prepend -- prepend stuff to a String * through -- make a SubString from beginning to match point * from -- make a SubString from match point to end * s[i] -- now returns the char by reference * BitVec's are no longer supported, since their capabilities are now incorporated in the revised BitString class. * stdarg.h and regex.h are revised to support the Sun4 * Several interesting and/or useful examples of libg++ class use are in ./etc, mainly courtesy of Doug Schmidt. * .cc file names are now all less than 15 characters. Some .h file names are longer, but this should not present problems on SYSV systems. * pseudo-generic `proto' classes have been thoroughly revised: * The prototype file names now end in `P', not `.proto' and are in the g++-include directory * A single, simple-to-use collection traversal mechanism via pseudo-indices (`Pix') is used instead of particular traversal friend classes. * `Bag' prototypes are included * Base classes are now supplied, so that all implementations of Sets, Bags, are derived, allowing programmers to mix and match implementations. * They are now simpler to create: all comparison operators and the like are now defined as macros in a `defs' file which uses some reasonable defaults. * The `Dictionary' versions of Set prototypes are not now supported. Revised versions of such classes are forthcoming. * Class prototypes previously labelled as `Assoc' are now called `Maps', with slightly different capabilities. * Splay tree prototypes are available. A bit more propaganda: Consider using Splay tree based containers (Set, Bag, Map, PQ). They are often the most efficient structures when performing mixtures of operations (adds, deletes, searches...) * Fixed precision reals are available, courtesy of Kurt Baudendistel * An ordered hash Set prototype (VOHSet) is available, courtesy of Doug Schmidt. * MLCG now allows access and modifications to the seeds. * The Normal random generator is fixed. * SampleStatistic now allows any prob value for confidence intervals. * some simple timer routines are in builtin.cc, courtesy of Doug Schmidt * While the Vec class prototypes are still available, they are currently undergoing revision in order to correspond to the forthcoming Matrix package (which should be available in the next libg++ release). * A C++ version of GPERF, a perfect hash function generator program is also available in ./etc, courtesy of Doug Schmidt. * changes from libg++-1.22.2 to libg++-1.25.0 * All reported errors from the previous release are fixed, and many suggested modifications have been performed. Thanks to all who have sent bug reports and comments, including those with mail addresses that I have not been able to reply to. (My mail connections are sometimes more than a little fragile. If you send me mail and I have not replied within a few days, you may want to try again. Sorry.) * A serious problem in the use of Obstacks by conversion functions has been repaired. * A bug in maintaining reference counts on `find' and related operations in List prototype classes has been fixed. * Strings now support self case manipulation in addition to the functional versions. * Some new functions have been added to builtin.[h.cc]. All are now documented in libg++.texinfo * Overload declarations are now performed in std.h and math.h, rather than builtin.h, to eliminate some include file ordering problems. * Random, RNG, and SampleStatistic classes are available, thanks to Dirk Grunwald. * A BitVec class is available. * The are many new generic container class prototype files. These support container classes based on elementary data structures (and a couple of non-elementary ones). Please read the documentation. * Class prototype OSet has been modified and renamed OLSet. * The genclass utility has been modified * changes from libg++-1.22.1 to 1.22.2 * Tests files are now in a separate directory. * Several minor errors (Complex unary -, several BitString functions) have been repaired. * pow(0,0) returns 1 for all versions of pow. * An experimental generic class prototyping feature is provided, including prototypes for lisp-style lists and ordered list-based sets. * several include files with the same names as those in AT&T CC are provided. These simply #include other files. OOPS should now compile using only g++-include files. See, however, the note about struct exception in file math.h * Some rearrangement of files containing char* conversion has been done to eliminate linking of unnecessary classes. * The inline-only-when-optimizing feature is still not supported. * New Random number generator classes are not yet available. Stubs for these files are in this directory. They should be available for next release. * changes from libg++-1.21.1 to 1.22.0 * All documentation is in a stand-alone texinfo file, libg++.texinfo, and is on its way to becoming a decent piece of documentation. * All reported errors from the previous release are fixed, and many suggested modifications have been performed. Thanks to all who have sent bug reports and comments, including those with mail addresses that I have not been able to reply to. (My mail connections are sometimes more than a little fragile. If you send me mail and I have not replied within a few days, you may want to try again. Sorry.) * New Complex, BitSet, and BitString classes are available. You will be performing a valuable service if you try these out and report back any bugs/comments/suggestions about these or any other classes. * File `values.h' has been added. This contains various system constants like the number of bits per long, etc. It contains much of the same information as sun , although a few names and things differ slightly. * Files `builtin.h', `builtin.cc', and `convert.cc' have been added. `builtin' contains common inline and non-inline functions on builtin types (like `abs'). `convert' contains code for performing IO and char* conversions, mainly via Obstacks. Most of these functions are not new -- they have been collected from other .h and .cc files. * Files `std.h' and `math.h' now declare all libc.a C functions in a way that allows any of them to be overloaded in C++. * Strings and Integers now perform expansion via realloc() -- see libconfig.h about whether you should #define SHOULD_FREE_TO_REALLOC. * `eatwhite' is supported for istreams. * File::getline(String, ...) and get(String) have been removed in order to maintain greater independence of different classes. * Strings now provide substring matching via new versions of `contains' and `matches', `common_prefix' and `common_suffix'. Also, there is more support for case operations via `fcompare', etc. The versions of `decompose' that do not deal with Regexes have been deleted since they provide little functionality over other operations. Also, a few special case functions dealing with char*'s have been deleted since the required constructors are necessary anyway. Several other corrections have been made in String.cc, including the elimination of a few aliasing problems. * The implementations of Integers and Rationals are now both much more efficient and well-tested, while remaining machine independent. A few minor visible features have been added and/or changed. * The `box' command in PlotFile is now simulated, whether or not it is present in libplot.a * The inlining-only-if-optimizing feature is still not fully implemented. her corrections libg++/etc/benchmarks/dhrystone.cc 600 473 0 53413 4677700000 12362 /****** A Version of the famous dhrystone benchmark ******* */ /* Sun Oct 1 10:40:53 1989 Doug Lea (dl at g.oswego.edu) Changes made to the standard version to run under C++: * include standard prototypes for printf and exit * include Int.h and Char.h * convert all `int' and `char' to `Int' and `Char' (except those needed for timing) * predeclare all functions * convert all function headers from old-C * Change name of struct tms tms to Tms * wrote mystrcpy and mystrcmp to handle Chars, not chars * added coercion to bad-looking Proc3 call in Proc1 * initialized String1Loc in Proc0 * use `new' instead of malloc This program is marginally useful in looking at the effects of various C++ constructs when defining a heavily constructive class like Int and Char. The Int.h and Char.h files can be compiled several ways, as listed at the top of each */ #include "Int.h" #include "Char.h" /* * "DHRYSTONE" Benchmark Program * * Version: C/1, 12/01/84 * * Date: PROGRAM updated 11/02/85, RESULTS updated 12/13/85 * * Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013 * Translated from ADA by Rick Richardson * Every method to preserve ADA-likeness has been used, * at the expense of C-ness. * * Compile: cc -O dry.c -o drynr : No registers * cc -O -DREG=register dry.c -o dryr : Registers * * Defines: Defines are provided for old C compiler's * which don't have enums, and can't assign structures. * The time(2) function is library dependant; Most * return the time in seconds, but beware of some, like * Aztec C, which return other units. * The LOOPS define is initially set for 50000 loops. * If you have a machine with large integers and is * very fast, please change this number to 500000 to * get better accuracy. Please select the way to * measure the execution time using the TIME define. * For single user machines, time(2) is adequate. For * multi-user machines where you cannot get single-user * access, use the times(2) function. If you have * neither, use a stopwatch in the dead of night. * Use a "printf" at the point marked "start timer" * to begin your timings. DO NOT use the UNIX "time(1)" * command, as this will measure the total time to * run this program, which will (erroneously) include * the time to malloc(3) storage and to compute the * time it takes to do nothing. * * Run: drynr; dryr * * Results: If you get any new machine/OS results, please send to: * * {ihnp4,vax135,..}!houxm!castor!pcrat!rer * * and thanks to all that do. Space prevents listing * the names of those who have provided some of these * results. * * Note: I order the list in increasing performance of the * "with registers" benchmark. If the compiler doesn't * provide register variables, then the benchmark * is the same for both REG and NOREG. I'm not going * to list a compiler in a better place because if it * had register variables it might do better. No * register variables is a big loss in my book. * * PLEASE: Send complete information about the machine type, * clock speed, OS and C manufacturer/version. If * the machine is modified, tell me what was done. * On UNIX, execute uname -a and cc -V to get this info. * * 80x8x NOTE: 80x8x benchers: please try to do all memory models * for a particular compiler. * *--------------------------------RESULTS BEGIN-------------------------------- * * MACHINE MICROPROCESSOR OPERATING COMPILER DHRYSTONES/SEC. * TYPE SYSTEM NO REG REGS * -------------------------- ------------ ----------- --------------- * Commodore 64 6510-1MHz C64 ROM C Power 2.8 36 36 * HP-110 8086-5.33Mhz MSDOS 2.11 Lattice 2.14 284 284 * IBM PC/XT 8088-4.77Mhz PC/IX cc 257 287 * P-E 3205 ? Xelos(SVR2) cc 279 296 * Perq-II 2901 bitslice Accent S5c cc (CMU) 301 301 * IBM PC/XT 8088-4.77Mhz COHERENT 2.3.43 MarkWilliams cc 296 317 * Cosmos 68000-8Mhz UniSoft cc 305 322 * IBM PC/XT 8088-4.77Mhz Venix/86 2.0 cc 297 324 * DEC PRO 350 11/23 Venix/PRO SVR2 cc 299 325 * PC/XT 8088-4.77Mhz Venix/86 SYS V cc 339 377 * IBM PC 8088-4.77Mhz MSDOS 2.0 b16cc 2.0 310 340 * Commodore Amiga ? Lattice 3.02 368 371 * IBM PC 8088-4.77Mhz MSDOS 2.0 CI-C86 2.20M 390 390 * IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Wizard 2.1 367 403 * IBM PC/XT 8088-4.77Mhz PCDOS 3.1 Lattice 2.15 403 403 @ * IBM PC 8088-4.77Mhz PCDOS 3.1 Datalight 1.10 416 416 * IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Microsoft 3.0 390 427 * PDP-11/34 - UNIX V7M cc 387 438 * IBM PC 8088, 4.77mhz PC-DOS 2.1 Aztec C v3.2d 423 454 * Tandy 1000 V20, 4.77mhz MS-DOS 2.11 Aztec C v3.2d 423 458 * PDP-11/34 - RSTS/E decus c 438 495 * Onyx C8002 Z8000-4Mhz IS/1 1.1 (V7) cc 476 511 * Perkin-Elmer 3230 Xelos (SysV.2) cc 507 565 * DEC PRO 380 11/73 Venix/PRO SVR2 cc 577 628 * FHL QT+ 68000-10Mhz Os9/68000 version 1.3 603 649 FH * Apollo DN550 68010-?Mhz AegisSR9/IX cc 3.12 666 666 * HP-110 8086-5.33Mhz MSDOS 2.11 Aztec-C 641 676 * ATT PC6300 8086-8Mhz MSDOS 2.11 b16cc 2.0 632 684 * IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.1 666 684 * Tandy 6000 68000-8Mhz Xenix 3.0 cc 694 694 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 684 704 MM * Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 32 bit int 694 704 * Macintosh 68000-7.7Mhz - MegaMax C 2.0 661 709 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 704 714 LM * Codata 3300 68000-8Mhz UniPlus+ (v7) cc 678 725 * Cadmus 9000 68010-10Mhz UNIX cc 714 735 * AT&T 6300 8086-8Mhz Venix/86 SVR2 cc 668 743 * Cadmus 9790 68010-10Mhz 1MB SVR0,Cadmus3.7 cc 720 747 * NEC PC9801F 8086-8Mhz PCDOS 2.11 Lattice 2.15 768 - @ * ATT PC6300 8086-8Mhz MSDOS 2.11 CI-C86 2.20M 769 769 * Burroughs XE550 68010-10Mhz Centix 2.10 cc 769 769 CT1 * EAGLE/TURBO 8086-8Mhz Venix/86 SVR2 cc 696 779 * ALTOS 586 8086-10Mhz Xenix 3.0b cc 724 793 * DEC 11/73 J-11 micro Ultrix-11 V3.0 System V 735 793 * ATT 3B2/300 WE32000-?Mhz UNIX 5.0.2 cc 735 806 * Apollo DN320 68010-?Mhz AegisSR9/IX cc 3.12 806 806 * IRIS-2400 68010-10Mhz UNIX System V cc 772 829 * Atari 520ST 68000-8Mhz TOS DigResearch 839 846 * IBM PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(large) 833 847 LM * VAX 11/750 - Ultrix 1.1 4.2BSD cc 781 862 * P-E 7350A 68000-8MHz UniSoft V.2 cc 821 875 * VAX 11/750 - UNIX 4.2bsd cc 862 877 * Fast Mac 68000-7.7Mhz - MegaMax C 2.0 839 904 + * IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Microsoft 3.0 833 909 C1 * DEC 11/44 Ultrix-11 V3.0 System V 862 909 * Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 16 bit int 877 909 S * P-E 3210 ? Xelos R01(SVR2) cc 849 924 * P-E 3220 ? Ed. 7 v2.3 cc 892 925 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc -i 909 925 * AT&T 6300 8086, 8mhz MS-DOS 2.11 Aztec C v3.2d 862 943 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 892 961 * VAX 11/750 w/FPA Eunice 3.2 cc 914 976 * IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Wizard 2.1 892 980 C1 * IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Lattice 2.15 980 980 C1 * Plexus P35 68000-10Mhz UNIX System III cc 984 980 * PDP-11/73 KDJ11-AA 15Mhz UNIX V7M 2.1 cc 862 981 * VAX 11/750 w/FPA UNIX 4.3bsd cc 994 997 * IRIS-1400 68010-10Mhz UNIX System V cc 909 1000 * IBM PC/AT 80286-6Mhz Venix/86 2.1 cc 961 1000 * IBM PC/AT 80286-6Mhz PCDOS 3.0 b16cc 2.0 943 1063 * Zilog S8000/11 Z8001-5.5Mhz Zeus 3.2 cc 1011 1084 * NSC ICM-3216 NSC 32016-10Mhz UNIX SVR2 cc 1041 1084 * IBM PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(small) 1063 1086 * VAX 11/750 w/FPA VMS VAX-11 C 2.0 958 1091 * Stride 68000-10Mhz System-V/68 cc 1041 1111 * ATT PC7300 68010-10Mhz UNIX 5.2 cc 1041 1111 * P-E 3230 ? Xelos R01(SVR2) cc 1040 1126 * Stride 68000-12Mhz System-V/68 cc 1063 1136 * IBM PC/AT 80286-6Mhz Venix/286 SVR2 cc 1056 1149 * IBM PC/AT 80286-6Mhz PCDOS 3.0 Datalight 1.10 1190 1190 * ATT PC6300+ 80286-6Mhz MSDOS 3.1 b16cc 2.0 1111 1219 * IBM PC/AT 80286-6Mhz PCDOS 3.1 Wizard 2.1 1136 1219 * Sun2/120 68010-10Mhz Sun 4.2BSD cc 1136 1219 * IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.20M 1219 1219 * MASSCOMP 500 68010-10MHz RTU V3.0 cc (V3.2) 1156 1238 * Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1162 1250 * PDP 11/70 - UNIX 5.2 cc 1162 1250 * IBM PC/AT 80286-6Mhz PCDOS 3.1 Lattice 2.15 1250 1250 * IBM PC/AT 80286-7.5Mhz Venix/86 2.1 cc 1190 1315 *15 * Sun2/120 68010-10Mhz Standalone cc 1219 1315 * Intel 380 80286-8Mhz Xenix R3.0up1 cc 1250 1315 *16 * ATT 3B2/400 WE32100-?Mhz UNIX 5.2 cc 1315 1315 * P-E 3250XP - Xelos R01(SVR2) cc 1215 1318 * DG MV4000 - AOS/VS 5.00 cc 1333 1333 * IBM PC/AT 80286-8Mhz Venix/86 2.1 cc 1275 1380 *16 * IBM PC/AT 80286-6Mhz MSDOS 3.0 Microsoft 3.0 1250 1388 * ATT PC6300+ 80286-6Mhz MSDOS 3.1 CI-C86 2.20M 1428 1428 * COMPAQ/286 80286-8Mhz Venix/286 SVR2 cc 1326 1443 * IBM PC/AT 80286-7.5Mhz Venix/286 SVR2 cc 1333 1449 *15 * Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1470 1562 S * VAX 11/780 - UNIX 5.2 cc 1515 1562 * MicroVAX-II - - - 1562 1612 * VAX 11/780 - UNIX 4.3bsd cc 1646 1662 * Apollo DN660 - AegisSR9/IX cc 3.12 1666 1666 * ATT 3B20 - UNIX 5.2 cc 1515 1724 * NEC PC-98XA 80286-8Mhz PCDOS 3.1 Lattice 2.15 1724 1724 @ * HP9000-500 B series CPU HP-UX 4.02 cc 1724 - * IBM PC/STD 80286-8Mhz MSDOS 3.0 Microsoft 3.0 1724 1785 C2 * DEC-2065 KL10-Model B TOPS-20 6.1FT5 Port. C Comp. 1937 1946 * Gould PN6005 - UTX 1.1(4.2BSD) cc 1675 1964 * DEC2060 KL-10 TOPS-20 cc 2000 2000 & * VAX 11/785 - UNIX 5.2 cc 2083 2083 * VAX 11/785 - VMS VAX-11 C 2.0 2083 2083 * VAX 11/785 - UNIX SVR2 cc 2123 2083 * VAX 11/785 - UNIX 4.3bsd cc 2135 2136 * Pyramid 90x - OSx 2.3 cc 2272 2272 * Pyramid 90x FPA,cache,4Mb OSx 2.5 cc no -O 2777 2777 * Alliant FX-8 CE ? ? 2622 2901 FX * Pyramid 90x w/cache OSx 2.5 cc w/-O 3333 3333 * IBM-4341-II - VM/SP3 Waterloo C 1.2 3333 3333 * IRIS-2400T 68020-16.67Mhz UNIX System V cc 3105 3401 * SUN 3/75 68020-16.67Mhz SUN 4.2 V3 cc 3333 3571 * IBM-4341 Model 12 UTS 5.0 ? 3685 3685 * SUN-3/160 68020-16.67Mhz Sun 4.2 V3.0A cc 3381 3764 * Sun 3/180 68020-16.67Mhz Sun 4.2 cc 3333 3846 * IBM-4341 Model 12 UTS 5.0 ? 3910 3910 MN * MC 5400 68020-16.67MHz RTU V3.0 cc (V4.0) 3952 4054 * NCR Tower32 68020-16.67Mhz SYS 5.0 Rel 2.0 cc 3846 4545 * Gould PN9080 - UTX-32 1.1c cc - 4629 * MC 5600/5700 68020-16.67MHz RTU V3.0 cc (V4.0) 4504 4746 % * Gould 1460-342 ECL proc UTX/32 1.1/c cc 5342 5677 G1 * VAX 8600 - UNIX 4.3bsd cc 7024 7088 * VAX 8600 - VMS VAX-11 C 2.0 7142 7142 * CCI POWER 6/32 COS(SV+4.2) cc 7500 7800 * CCI POWER 6/32 POWER 6 UNIX/V cc 8236 8498 * CCI POWER 6/32 4.2 Rel. 1.2b cc 8963 9544 * Sperry (CCI Power 6) 4.2BSD cc 9345 10000 * CRAY-X-MP/12 105Mhz COS 1.14 Cray C 10204 10204 * IBM-3083 - UTS 5.0 Rel 1 cc 16666 12500 * CRAY-1A 80Mhz CTSS Cray C 2.0 12100 13888 * IBM-3083 - VM/CMS HPO 3.4 Waterloo C 1.2 13889 13889 * Amdahl 470 V/8 UTS/V 5.2 cc v1.23 15560 15560 * CRAY-X-MP/48 105Mhz CTSS Cray C 2.0 15625 17857 * Amdahl 580 - UTS 5.0 Rel 1.2 cc v1.5 23076 23076 * Amdahl 5860 UTS/V 5.2 cc v1.23 28970 28970 * * * Crystal changed from 'stock' to listed value. * + This Macintosh was upgraded from 128K to 512K in such a way that * the new 384K of memory is not slowed down by video generator accesses. * % Single processor; MC == MASSCOMP * & A version 7 C compiler written at New Mexico Tech. * @ vanilla Lattice compiler used with MicroPro standard library * S Shorts used instead of ints * LM Large Memory Model. (Otherwise, all 80x8x results are small model) * MM Medium Memory Model. (Otherwise, all 80x8x results are small model) * C1 Univation PC TURBO Co-processor; 9.54Mhz 8086, 640K RAM * C2 Seattle Telecom STD-286 board * C? Unknown co-processor board? * CT1 Convergent Technologies MegaFrame, 1 processor. * MN Using Mike Newtons 'optimizer' (see net.sources). * G1 This Gould machine has 2 processors and was able to run 2 dhrystone * Benchmarks in parallel with no slowdown. * FH FHC == Frank Hogg Labs (Hazelwood Uniquad 2 in an FHL box). * FX The FX-8 has two kinds of processors. This figure is for CE's * (computation engines). The other processor type is an IP (interactive * processor) which is a 68010-12Mhz. Figures were not precisely * determined for the IP. * ? I don't trust results marked with '?'. These were sent to me with * either incomplete info, or with times that just don't make sense. * ?? means I think the performance is too poor, ?! means too good. * If anybody can confirm these figures, please respond. * *--------------------------------RESULTS END---------------------------------- * * The following program contains statements of a high-level programming * language (C) in a distribution considered representative: * * assignments 53% * control statements 32% * procedure, function calls 15% * * 100 statements are dynamically executed. The program is balanced with * respect to the three aspects: * - statement type * - operand type (for simple data types) * - operand access * operand global, local, parameter, or constant. * * The combination of these three aspects is balanced only approximately. * * The program does not compute anything meaningfull, but it is * syntactically and semantically correct. * */ /* Accuracy of timings and human fatigue controlled by next two lines */ #ifdef QUICK #define LOOPS 50000 /* Use this for slow or 16 bit machines */ #else #define LOOPS 500000 /* Use this for faster machines */ #endif /* Compiler dependent options */ #undef NOENUM /* Define if compiler has no enum's */ #undef NOSTRUCTASSIGN /* Define if compiler can't assign structures */ /* define only one of the next two defines */ #ifndef USG #define TIMES /* Use times(2) time function */ #else #define TIME /* Use time(2) time function */ #endif #ifdef TIMES #include #include #endif /* define the granularity of your times(2) function (when used) */ #ifndef HZ #define HZ 60 /* times(2) returns 1/60 second (most) */ /*#define HZ 100 /* times(2) returns 1/100 second (WECo) */ #endif #ifdef NOSTRUCTASSIGN #define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) #else #define structassign(d, s) d = s #endif #ifdef NOENUM #define Ident1 1 #define Ident2 2 #define Ident3 3 #define Ident4 4 #define Ident5 5 typedef int Enumeration; #else typedef enum {Ident1, Ident2, Ident3, Ident4, Ident5} Enumeration; #endif typedef Int OneToThirty; typedef Int OneToFifty; typedef Char CapitalLetter; typedef Char String30[31]; typedef Int Array1Dim[51]; typedef Int Array2Dim[51][51]; struct Record { struct Record *PtrComp; Enumeration Discr; Enumeration EnumComp; OneToFifty IntComp; String30 StringComp; }; typedef struct Record RecordType; typedef RecordType * RecordPtr; typedef int boolean; #define NULL 0 #define TRUE 1 #define FALSE 0 #ifndef REG #define REG #endif /* added: - dl */ extern "C" { extern int printf(const char* ...); extern void exit(int); } void Proc0(); void Proc1(RecordPtr PtrParIn); void Proc2(OneToFifty *IntParIO); void Proc3(RecordPtr *PtrParOut); void Proc4(); void Proc5(); boolean Func3(Enumeration EnumParIn); void Proc6(REG Enumeration EnumParIn, REG Enumeration *EnumParOut); void Proc7(OneToFifty IntParI1, OneToFifty IntParI2, OneToFifty *IntParOut); void Proc8(Array1Dim Array1Par, Array2Dim Array2Par, OneToFifty IntParI1, OneToFifty IntParI2); Enumeration Func1(CapitalLetter CharPar1, CapitalLetter CharPar2); boolean Func2(String30 StrParI1, String30 StrParI2); boolean Func3(Enumeration EnumParIn); void mystrcpy(String30 s, char* t) { for (; *t != '\0'; ++s, ++t) *s = *t; *s = '\0'; } char mystrcmp(String30 s, String30 t) { for (; *s == *t; ++s, ++t) if (*s == '\0') return 0; return char(*s - *t); } /*end - dl */ main() { Proc0(); exit(0); } /* * Package 1 */ Int IntGlob; boolean BoolGlob; char Char1Glob; char Char2Glob; Array1Dim Array1Glob; Array2Dim Array2Glob; RecordPtr PtrGlb; RecordPtr PtrGlbNext; void Proc0() { OneToFifty IntLoc1; REG OneToFifty IntLoc2; OneToFifty IntLoc3; REG char CharLoc; REG char CharIndex; Enumeration EnumLoc; String30 String1Loc; String30 String2Loc; #ifdef TIME long time(); long starttime; long benchtime; long nulltime; register unsigned int i; starttime = time( (long *) 0); for (i = 0; i < LOOPS; ++i); nulltime = time( (long *) 0) - starttime; /* Computes o'head of loop */ #endif #ifdef TIMES time_t starttime; time_t benchtime; time_t nulltime; struct tms Tms; register unsigned int i; times(&Tms); starttime = Tms.tms_utime; for (i = 0; i < LOOPS; ++i); times(&Tms); nulltime = Tms.tms_utime - starttime; /* Computes overhead of looping */ #endif PtrGlbNext = new Record; PtrGlb = new Record; PtrGlb->PtrComp = PtrGlbNext; PtrGlb->Discr = Ident1; PtrGlb->EnumComp = Ident3; PtrGlb->IntComp = 40; mystrcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING"); mystrcpy(String1Loc, "JUST INITIALIZED TO SOME JUNK."); /***************** -- Start Timer -- *****************/ #ifdef TIME starttime = time( (long *) 0); #endif #ifdef TIMES times(&Tms); starttime = Tms.tms_utime; #endif for (i = 0; i < LOOPS; ++i) { Proc5(); Proc4(); IntLoc1 = 2; IntLoc2 = 3; mystrcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); EnumLoc = Ident2; BoolGlob = ! Func2(String1Loc, String2Loc); while (IntLoc1 < IntLoc2) { IntLoc3 = 5 * IntLoc1 - IntLoc2; Proc7(IntLoc1, IntLoc2, &IntLoc3); ++IntLoc1; } Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3); Proc1(PtrGlb); for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex) if (EnumLoc == Func1(CharIndex, 'C')) Proc6(Ident1, &EnumLoc); IntLoc3 = IntLoc2 * IntLoc1; IntLoc2 = IntLoc3 / IntLoc1; IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1; Proc2(&IntLoc1); } /***************** -- Stop Timer -- *****************/ #ifdef TIME benchtime = time( (long *) 0) - starttime - nulltime; printf("Dhrystone time for %ld passes = %ld\n", (long) LOOPS, benchtime); printf("This machine benchmarks at %ld dhrystones/second\n", ((long) LOOPS) / benchtime); #endif #ifdef TIMES times(&Tms); benchtime = Tms.tms_utime - starttime - nulltime; printf("Dhrystone time for %ld passes = %ld\n", (long) LOOPS, benchtime/HZ); printf("This machine benchmarks at %ld dhrystones/second\n", ((long) LOOPS) * HZ / benchtime); #endif } void Proc1(RecordPtr PtrParIn) { #define NextRecord (*(PtrParIn->PtrComp)) structassign(NextRecord, *PtrGlb); PtrParIn->IntComp = 5; NextRecord.IntComp = PtrParIn->IntComp; NextRecord.PtrComp = PtrParIn->PtrComp; /* - added coercion (glossing over error in original code) - dl */ Proc3(&(NextRecord.PtrComp)); if (NextRecord.Discr == Ident1) { NextRecord.IntComp = 6; Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp); NextRecord.PtrComp = PtrGlb->PtrComp; Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp); } else structassign(*PtrParIn, NextRecord); #undef NextRecord } void Proc2(OneToFifty *IntParIO) { REG OneToFifty IntLoc; REG Enumeration EnumLoc; IntLoc = *IntParIO + 10; for(;;) { if (Char1Glob == 'A') { --IntLoc; *IntParIO = IntLoc - IntGlob; EnumLoc = Ident1; } if (EnumLoc == Ident1) break; } } void Proc3(RecordPtr *PtrParOut) { if (PtrGlb != NULL) *PtrParOut = PtrGlb->PtrComp; else IntGlob = 100; Proc7(10, IntGlob, &PtrGlb->IntComp); } void Proc4() { REG boolean BoolLoc; BoolLoc = Char1Glob == 'A'; BoolLoc |= BoolGlob; Char2Glob = 'B'; } void Proc5() { Char1Glob = 'A'; BoolGlob = FALSE; } void Proc6(REG Enumeration EnumParIn, REG Enumeration *EnumParOut) { *EnumParOut = EnumParIn; if (! Func3(EnumParIn) ) *EnumParOut = Ident4; switch (EnumParIn) { case Ident1: *EnumParOut = Ident1; break; case Ident2: if (IntGlob > 100) *EnumParOut = Ident1; else *EnumParOut = Ident4; break; case Ident3: *EnumParOut = Ident2; break; case Ident4: break; case Ident5: *EnumParOut = Ident3; } } void Proc7(OneToFifty IntParI1, OneToFifty IntParI2, OneToFifty *IntParOut) { REG OneToFifty IntLoc; IntLoc = IntParI1 + 2; *IntParOut = IntParI2 + IntLoc; } void Proc8(Array1Dim Array1Par, Array2Dim Array2Par, OneToFifty IntParI1, OneToFifty IntParI2) { REG OneToFifty IntLoc; REG OneToFifty IntIndex; IntLoc = IntParI1 + 5; Array1Par[IntLoc] = IntParI2; Array1Par[IntLoc+1] = Array1Par[IntLoc]; Array1Par[IntLoc+30] = IntLoc; for (IntIndex = IntLoc; IntIndex <= (IntLoc+1); ++IntIndex) Array2Par[IntLoc][IntIndex] = IntLoc; ++Array2Par[IntLoc][IntLoc-1]; Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc]; IntGlob = 5; } Enumeration Func1(CapitalLetter CharPar1, CapitalLetter CharPar2) { REG CapitalLetter CharLoc1; REG CapitalLetter CharLoc2; CharLoc1 = CharPar1; CharLoc2 = CharLoc1; if (CharLoc2 != CharPar2) return (Ident1); else return (Ident2); } boolean Func2(String30 StrParI1, String30 StrParI2) { REG OneToThirty IntLoc; REG CapitalLetter CharLoc; IntLoc = 1; while (IntLoc <= 1) if (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1) { CharLoc = 'A'; ++IntLoc; } if (CharLoc >= 'W' && CharLoc <= 'Z') IntLoc = 7; if (CharLoc == 'X') return(TRUE); else { if (mystrcmp(StrParI1, StrParI2) > 0) { IntLoc += 7; return (TRUE); } else return (FALSE); } } boolean Func3(Enumeration EnumParIn) { REG Enumeration EnumLoc; EnumLoc = EnumParIn; if (EnumLoc == Ident3) return (TRUE); return (FALSE); } #ifdef NOSTRUCTASSIGN memcpy(d, s, l) register char *d; register char *s; int l; { while (l--) *d++ = *s++; } #endif CharLoc = 'A'; ++IntLoc; } if (CharLoc >= 'W' && CharLoc <= 'Z') IntLoc = 7; if (CharLoc == 'X') return(TRUE); else { if (mystrcmp(StrParI1, StrParI2) > 0) { IntLoc += 7; return (TRUE); } else return (FALSE); } } libg++/etc/benchmarks/Char.h 600 473 0 36212 4677700000 11060 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Char_h #pragma once #define _Char_h 1 /* compile with -DBUILTIN - to get standard chars -DCALL - to get calls instead of inlines (in which case don't use -finline-functions!) -DVIRT - to make all members virtual -DBYVAL - to use call-by-value, not by-reference -DNO_GNU_CONST - to eliminate calling const functions const -DCONVERT - to eliminate mixed mode fns that avoid constructors -DNO_NRV - to eliminate use of named return values -DFAKEVPTR - to get one pocharer per object padding -DRETREF - to make =, +=, etc. return *this, not void */ #ifdef BUILTIN typedef char Char; #else #ifdef CALL #define INLINE #else #define INLINE inline #endif #ifndef VIRT #define VIRTUAL #else #define VIRTUAL virtual #endif #ifdef BYVAL #define REF #else #define REF & #endif #ifndef NO_GNU_CONST #define CONSTFN const #else #define CONSTFN #endif #ifndef CONVERT #define EXPLICIT #endif #ifndef RETREF #define CharR void #define ReturnCharR #else #define CharR Char& #define ReturnCharr return *this #endif class Char { protected: char rep; #ifdef FAKEVPTR void* fake_vptr; #endif public: Char (); Char (const char b); Char (const Char& b); ~Char(); operator char() const; VIRTUAL char CONSTFN val() const; VIRTUAL CharR operator = (const char); VIRTUAL CharR operator = (const Char&); VIRTUAL CharR negate(); VIRTUAL CharR complement(); VIRTUAL CharR operator ++ (); VIRTUAL CharR operator -- (); VIRTUAL CharR operator += (const Char REF ); VIRTUAL CharR operator -= (const Char REF ); VIRTUAL CharR operator *= (const Char REF ); VIRTUAL CharR operator /= (const Char REF ); VIRTUAL CharR operator %= (const Char REF ); VIRTUAL CharR operator |= (const Char REF ); VIRTUAL CharR operator &= (const Char REF ); VIRTUAL CharR operator ^= (const Char REF ); VIRTUAL CharR operator <<=(const Char REF ); VIRTUAL CharR operator >>=(const Char REF ); #ifdef EXPLICIT VIRTUAL CharR operator += (const char); VIRTUAL CharR operator -= (const char); VIRTUAL CharR operator *= (const char); VIRTUAL CharR operator /= (const char); VIRTUAL CharR operator %= (const char); VIRTUAL CharR operator |= (const char); VIRTUAL CharR operator &= (const char); VIRTUAL CharR operator ^= (const char); VIRTUAL CharR operator <<=(const char); VIRTUAL CharR operator >>=(const char); #endif }; INLINE char CONSTFN Char::val() const { return rep; } INLINE Char::operator char() const { return val(); } INLINE Char::Char () :rep(0) {} INLINE Char::Char (const char b) :rep(b) {} INLINE Char::Char (const Char& b) :rep(b.Char::val()) {} INLINE Char::~Char() {} INLINE CharR Char::operator = (const char b) { rep = b; ReturnCharR; } INLINE CharR Char::operator = (const Char& b) { rep = b.Char::val(); ReturnCharR; } INLINE CharR Char::complement() { rep = ~rep; ReturnCharR; } INLINE CharR Char::negate() { rep = -rep; ReturnCharR; } INLINE CharR Char::operator ++ () { ++rep; ReturnCharR; } INLINE CharR Char::operator -- () { --rep; ReturnCharR; } INLINE CharR Char::operator += (const Char REF b) { rep += b.Char::val(); ReturnCharR; } INLINE CharR Char::operator -= (const Char REF b) { rep -= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator *= (const Char REF b) { rep *= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator /= (const Char REF b) { rep /= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator %= (const Char REF b) { rep %= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator |= (const Char REF b) { rep |= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator &= (const Char REF b) { rep &= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator ^= (const Char REF b) { rep ^= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator <<=(const Char REF b) { rep <<= b.Char::val(); ReturnCharR; } INLINE CharR Char::operator >>=(const Char REF b) { rep >>= b.Char::val(); ReturnCharR; } #ifdef EXPLICIT INLINE CharR Char::operator += (const char b) { rep += b; ReturnCharR; } INLINE CharR Char::operator -= (const char b) { rep -= b; ReturnCharR; } INLINE CharR Char::operator *= (const char b) { rep *= b; ReturnCharR; } INLINE CharR Char::operator /= (const char b) { rep /= b; ReturnCharR; } INLINE CharR Char::operator %= (const char b) { rep %= b; ReturnCharR; } INLINE CharR Char::operator |= (const char b) { rep |= b; ReturnCharR; } INLINE CharR Char::operator &= (const char b) { rep &= b; ReturnCharR; } INLINE CharR Char::operator ^= (const char b) { rep ^= b; ReturnCharR; } INLINE CharR Char::operator <<=(const char b) { rep <<= b; ReturnCharR; } INLINE CharR Char::operator >>=(const char b) { rep >>= b; ReturnCharR; } INLINE char& operator = (char& a, const Char REF b) { a = b.Char::val(); return a;} INLINE char& operator += (char& a, const Char REF b) { a += b.Char::val(); return a; } INLINE char& operator -= (char& a, const Char REF b) { a -= b.Char::val(); return a;} INLINE char& operator *= (char& a, const Char REF b) { a *= b.Char::val(); return a;} INLINE char& operator /= (char& a, const Char REF b) { a /= b.Char::val(); return a;} INLINE char& operator %= (char& a, const Char REF b) { a %= b.Char::val(); return a;} INLINE char& operator |= (char& a, const Char REF b) { a |= b.Char::val(); return a;} INLINE char& operator &= (char& a, const Char REF b) { a &= b.Char::val(); return a;} INLINE char& operator ^= (char& a, const Char REF b) { a ^= b.Char::val(); return a;} INLINE char& operator <<=(char& a, const Char REF b) { a <<= b.Char::val(); return a;} INLINE char& operator >>=(char& a, const Char REF b) { a >>= b.Char::val(); return a;} #endif #ifdef NO_NRV INLINE Char CONSTFN operator - (const Char REF a) { Char r(a); r.negate(); return r; } INLINE Char CONSTFN operator ~ (const Char REF a) { Char r(a); r.complement(); return r; } INLINE Char CONSTFN operator + (const Char REF a, const Char REF b) { Char r(a); r += b.Char::val(); return r; } INLINE Char CONSTFN operator - (const Char REF a, const Char REF b) { Char r(a); r -= b.Char::val(); return r; } INLINE Char CONSTFN operator * (const Char REF a, const Char REF b) { Char r(a); r *= b.Char::val(); return r; } INLINE Char CONSTFN operator / (const Char REF a, const Char REF b) { Char r(a); r /= b.Char::val(); return r; } INLINE Char CONSTFN operator % (const Char REF a, const Char REF b) { Char r(a); r %= b.Char::val(); return r; } INLINE Char CONSTFN operator << (const Char REF a, const Char REF b) { Char r(a); r <<= b.Char::val(); return r; } INLINE Char CONSTFN operator >> (const Char REF a, const Char REF b) { Char r(a); r >>= b.Char::val(); return r; } INLINE Char CONSTFN operator & (const Char REF a, const Char REF b) { Char r(a); r &= b.Char::val(); return r; } INLINE Char CONSTFN operator | (const Char REF a, const Char REF b) { Char r(a); r |= b.Char::val(); return r; } INLINE Char CONSTFN operator ^ (const Char REF a, const Char REF b) { Char r(a); r ^= b.Char::val(); return r; } INLINE Char CONSTFN operator + (const Char REF a, const char b) { Char r(a); r += b; return r; } INLINE Char CONSTFN operator - (const Char REF a, const char b) { Char r(a); r -= b; return r; } INLINE Char CONSTFN operator * (const Char REF a, const char b) { Char r(a); r *= b; return r; } INLINE Char CONSTFN operator / (const Char REF a, const char b) { Char r(a); r /= b; return r; } INLINE Char CONSTFN operator % (const Char REF a, const char b) { Char r(a); r %= b; return r; } INLINE Char CONSTFN operator << (const Char REF a, const char b) { Char r(a); r <<= b; return r; } INLINE Char CONSTFN operator >> (const Char REF a, const char b) { Char r(a); r >>= b; return r; } INLINE Char CONSTFN operator & (const Char REF a, const char b) { Char r(a); r &= b; return r; } INLINE Char CONSTFN operator | (const Char REF a, const char b) { Char r(a); r |= b; return r; } INLINE Char CONSTFN operator ^ (const Char REF a, const char b) { Char r(a); r ^= b; return r; } INLINE Char CONSTFN operator + (const char a, const Char REF b) { Char r(a); r += b.Char::val(); return r; } INLINE Char CONSTFN operator - (const char a, const Char REF b) { Char r(a); r -= b.Char::val(); return r; } INLINE Char CONSTFN operator * (const char a, const Char REF b) { Char r(a); r *= b.Char::val(); return r; } INLINE Char CONSTFN operator / (const char a, const Char REF b) { Char r(a); r /= b.Char::val(); return r; } INLINE Char CONSTFN operator % (const char a, const Char REF b) { Char r(a); r %= b.Char::val(); return r; } INLINE Char CONSTFN operator << (const char a, const Char REF b) { Char r(a); r <<= b.Char::val(); return r; } INLINE Char CONSTFN operator >> (const char a, const Char REF b) { Char r(a); r >>= b.Char::val(); return r; } INLINE Char CONSTFN operator & (const char a, const Char REF b) { Char r(a); r &= b.Char::val(); return r; } INLINE Char CONSTFN operator | (const char a, const Char REF b) { Char r(a); r |= b.Char::val(); return r; } INLINE Char CONSTFN operator ^ (const char a, const Char REF b) { Char r(a); r ^= b.Char::val(); return r; } #else INLINE Char CONSTFN operator - (const Char REF a) return r(a) { r.negate(); } INLINE Char CONSTFN operator ~ (const Char REF a) return r(a) { r.complement(); } INLINE Char CONSTFN operator + (const Char REF a, const Char REF b) return r(a) { r += b.Char::val(); } INLINE Char CONSTFN operator - (const Char REF a, const Char REF b) return r(a) { r -= b.Char::val(); } INLINE Char CONSTFN operator * (const Char REF a, const Char REF b) return r(a) { r *= b.Char::val(); } INLINE Char CONSTFN operator / (const Char REF a, const Char REF b) return r(a) { r /= b.Char::val(); } INLINE Char CONSTFN operator % (const Char REF a, const Char REF b) return r(a) { r %= b.Char::val(); } INLINE Char CONSTFN operator << (const Char REF a, const Char REF b) return r(a) { r <<= b.Char::val(); } INLINE Char CONSTFN operator >> (const Char REF a, const Char REF b) return r(a) { r >>= b.Char::val(); } INLINE Char CONSTFN operator & (const Char REF a, const Char REF b) return r(a) { r &= b.Char::val(); } INLINE Char CONSTFN operator | (const Char REF a, const Char REF b) return r(a) { r |= b.Char::val(); } INLINE Char CONSTFN operator ^ (const Char REF a, const Char REF b) return r(a) { r ^= b.Char::val(); } INLINE Char CONSTFN operator + (const Char REF a, const char b) return r(a) { r += b; } INLINE Char CONSTFN operator - (const Char REF a, const char b) return r(a) { r -= b; } INLINE Char CONSTFN operator * (const Char REF a, const char b) return r(a) { r *= b; } INLINE Char CONSTFN operator / (const Char REF a, const char b) return r(a) { r /= b; } INLINE Char CONSTFN operator % (const Char REF a, const char b) return r(a) { r %= b; } INLINE Char CONSTFN operator << (const Char REF a, const char b) return r(a) { r <<= b; } INLINE Char CONSTFN operator >> (const Char REF a, const char b) return r(a) { r >>= b; } INLINE Char CONSTFN operator & (const Char REF a, const char b) return r(a) { r &= b; } INLINE Char CONSTFN operator | (const Char REF a, const char b) return r(a) { r |= b; } INLINE Char CONSTFN operator ^ (const Char REF a, const char b) return r(a) { r ^= b; } INLINE Char CONSTFN operator + (const char a, const Char REF b) return r(a) { r += b.Char::val(); } INLINE Char CONSTFN operator - (const char a, const Char REF b) return r(a) { r -= b.Char::val(); } INLINE Char CONSTFN operator * (const char a, const Char REF b) return r(a) { r *= b.Char::val(); } INLINE Char CONSTFN operator / (const char a, const Char REF b) return r(a) { r /= b.Char::val(); } INLINE Char CONSTFN operator % (const char a, const Char REF b) return r(a) { r %= b.Char::val(); } INLINE Char CONSTFN operator << (const char a, const Char REF b) return r(a) { r <<= b.Char::val(); } INLINE Char CONSTFN operator >> (const char a, const Char REF b) return r(a) { r >>= b.Char::val(); } INLINE Char CONSTFN operator & (const char a, const Char REF b) return r(a) { r &= b.Char::val(); } INLINE Char CONSTFN operator | (const char a, const Char REF b) return r(a) { r |= b.Char::val(); } INLINE Char CONSTFN operator ^ (const char a, const Char REF b) return r(a) { r ^= b.Char::val(); } #endif INLINE char CONSTFN operator ! (const Char REF a) { return !a.Char::val(); } INLINE char CONSTFN operator == (const Char REF a, const Char REF b) { return a.Char::val() == b.Char::val(); } INLINE char CONSTFN operator != (const Char REF a, const Char REF b) { return a.Char::val() != b.Char::val(); } INLINE char CONSTFN operator < (const Char REF a, const Char REF b) { return a.Char::val() < b.Char::val(); } INLINE char CONSTFN operator <= (const Char REF a, const Char REF b) { return a.Char::val() <= b.Char::val(); } INLINE char CONSTFN operator > (const Char REF a, const Char REF b) { return a.Char::val() > b.Char::val(); } INLINE char CONSTFN operator >= (const Char REF a, const Char REF b) { return a.Char::val() >= b.Char::val(); } INLINE char CONSTFN operator == (const Char REF a, const char b) { return a.Char::val() == b; } INLINE char CONSTFN operator != (const Char REF a, const char b) { return a.Char::val() != b; } INLINE char CONSTFN operator < (const Char REF a, const char b) { return a.Char::val() < b; } INLINE char CONSTFN operator <= (const Char REF a, const char b) { return a.Char::val() <= b; } INLINE char CONSTFN operator > (const Char REF a, const char b) { return a.Char::val() > b; } INLINE char CONSTFN operator >= (const Char REF a, const char b) { return a.Char::val() >= b; } INLINE char CONSTFN operator == (const char a, const Char REF b) { return a == b.Char::val(); } INLINE char CONSTFN operator != (const char a, const Char REF b) { return a != b.Char::val(); } INLINE char CONSTFN operator < (const char a, const Char REF b) { return a < b.Char::val(); } INLINE char CONSTFN operator <= (const char a, const Char REF b) { return a <= b.Char::val(); } INLINE char CONSTFN operator > (const char a, const Char REF b) { return a > b.Char::val(); } INLINE char CONSTFN operator >= (const char a, const Char REF b) { return a >= b.Char::val(); } #endif #endif l(); } INLINE char CONSTFN operator != (const char a, const Char REF b) { return a != b.Char::val(); } INLINE char CONSTFN operator < (const char a, const Char REF b) { return a < b.Char::val(); } INLINE char CONSTFN operator <= (const char a, const Char REF b) { return a <= b.Char::val(); } INLINE char CONSTFN operator > (const char a, const Char REF b) { retulibg++/etc/benchmarks/Int.h 600 473 0 35106 4677700000 10736 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Int_h #pragma once #define _Int_h 1 /* compile with -DBUILTIN - to get standard ints -DCALL - to get calls instead of inlines (in which case don't use -finline-functions!) -DVIRT - to make all members virtual -DBYVAL - to use call-by-value, not by-reference -DNO_GNU_CONST - to eliminate calling const functions const -DCONVERT - to eliminate mixed mode fns that avoid constructors -DNO_NRV - to eliminate use of named return values -DFAKEVPTR - to get one pointer per object padding -DRETREF - to make =, +=, etc. return *this, not void */ #ifdef BUILTIN typedef int Int; #else #ifdef CALL #define INLINE #else #define INLINE inline #endif #ifndef VIRT #define VIRTUAL #else #define VIRTUAL virtual #endif #ifdef BYVAL #define REF #else #define REF & #endif #ifndef NO_GNU_CONST #define CONSTFN const #else #define CONSTFN #endif #ifndef CONVERT #define EXPLICIT #endif #ifndef RETREF #define IntR void #define ReturnIntR #else #define IntR Int& #define ReturnIntr return *this #endif class Int { protected: int rep; #ifdef FAKEVPTR void* fake_vptr; #endif public: Int (); Int (const int b); Int (const Int& b); ~Int(); operator int() const; VIRTUAL int CONSTFN val() const; VIRTUAL IntR operator = (const int); VIRTUAL IntR operator = (const Int&); VIRTUAL IntR negate(); VIRTUAL IntR complement(); VIRTUAL IntR operator ++ (); VIRTUAL IntR operator -- (); VIRTUAL IntR operator += (const Int REF ); VIRTUAL IntR operator -= (const Int REF ); VIRTUAL IntR operator *= (const Int REF ); VIRTUAL IntR operator /= (const Int REF ); VIRTUAL IntR operator %= (const Int REF ); VIRTUAL IntR operator |= (const Int REF ); VIRTUAL IntR operator &= (const Int REF ); VIRTUAL IntR operator ^= (const Int REF ); VIRTUAL IntR operator <<=(const Int REF ); VIRTUAL IntR operator >>=(const Int REF ); #ifdef EXPLICIT VIRTUAL IntR operator += (const int); VIRTUAL IntR operator -= (const int); VIRTUAL IntR operator *= (const int); VIRTUAL IntR operator /= (const int); VIRTUAL IntR operator %= (const int); VIRTUAL IntR operator |= (const int); VIRTUAL IntR operator &= (const int); VIRTUAL IntR operator ^= (const int); VIRTUAL IntR operator <<=(const int); VIRTUAL IntR operator >>=(const int); #endif }; INLINE int CONSTFN Int::val() const { return rep; } INLINE Int::operator int() const { return val(); } INLINE Int::Int () :rep(0) {} INLINE Int::Int (const int b) :rep(b) {} INLINE Int::Int (const Int& b) :rep(b.Int::val()) {} INLINE Int::~Int() {} INLINE IntR Int::operator = (const int b) { rep = b; ReturnIntR; } INLINE IntR Int::operator = (const Int& b) { rep = b.Int::val(); ReturnIntR; } INLINE IntR Int::complement() { rep = ~rep; ReturnIntR; } INLINE IntR Int::negate() { rep = -rep; ReturnIntR; } INLINE IntR Int::operator ++ () { ++rep; ReturnIntR; } INLINE IntR Int::operator -- () { --rep; ReturnIntR; } INLINE IntR Int::operator += (const Int REF b) { rep += b.Int::val(); ReturnIntR; } INLINE IntR Int::operator -= (const Int REF b) { rep -= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator *= (const Int REF b) { rep *= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator /= (const Int REF b) { rep /= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator %= (const Int REF b) { rep %= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator |= (const Int REF b) { rep |= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator &= (const Int REF b) { rep &= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator ^= (const Int REF b) { rep ^= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator <<=(const Int REF b) { rep <<= b.Int::val(); ReturnIntR; } INLINE IntR Int::operator >>=(const Int REF b) { rep >>= b.Int::val(); ReturnIntR; } #ifdef EXPLICIT INLINE IntR Int::operator += (const int b) { rep += b; ReturnIntR; } INLINE IntR Int::operator -= (const int b) { rep -= b; ReturnIntR; } INLINE IntR Int::operator *= (const int b) { rep *= b; ReturnIntR; } INLINE IntR Int::operator /= (const int b) { rep /= b; ReturnIntR; } INLINE IntR Int::operator %= (const int b) { rep %= b; ReturnIntR; } INLINE IntR Int::operator |= (const int b) { rep |= b; ReturnIntR; } INLINE IntR Int::operator &= (const int b) { rep &= b; ReturnIntR; } INLINE IntR Int::operator ^= (const int b) { rep ^= b; ReturnIntR; } INLINE IntR Int::operator <<=(const int b) { rep <<= b; ReturnIntR; } INLINE IntR Int::operator >>=(const int b) { rep >>= b; ReturnIntR; } INLINE int& operator = (int& a, const Int REF b) { a = b.Int::val(); return a;} INLINE int& operator += (int& a, const Int REF b) { a += b.Int::val(); return a; } INLINE int& operator -= (int& a, const Int REF b) { a -= b.Int::val(); return a;} INLINE int& operator *= (int& a, const Int REF b) { a *= b.Int::val(); return a;} INLINE int& operator /= (int& a, const Int REF b) { a /= b.Int::val(); return a;} INLINE int& operator %= (int& a, const Int REF b) { a %= b.Int::val(); return a;} INLINE int& operator |= (int& a, const Int REF b) { a |= b.Int::val(); return a;} INLINE int& operator &= (int& a, const Int REF b) { a &= b.Int::val(); return a;} INLINE int& operator ^= (int& a, const Int REF b) { a ^= b.Int::val(); return a;} INLINE int& operator <<=(int& a, const Int REF b) { a <<= b.Int::val(); return a;} INLINE int& operator >>=(int& a, const Int REF b) { a >>= b.Int::val(); return a;} #endif #ifdef NO_NRV INLINE Int CONSTFN operator - (const Int REF a) { Int r(a); r.negate(); return r; } INLINE Int CONSTFN operator ~ (const Int REF a) { Int r(a); r.complement(); return r; } INLINE Int CONSTFN operator + (const Int REF a, const Int REF b) { Int r(a); r += b.Int::val(); return r; } INLINE Int CONSTFN operator - (const Int REF a, const Int REF b) { Int r(a); r -= b.Int::val(); return r; } INLINE Int CONSTFN operator * (const Int REF a, const Int REF b) { Int r(a); r *= b.Int::val(); return r; } INLINE Int CONSTFN operator / (const Int REF a, const Int REF b) { Int r(a); r /= b.Int::val(); return r; } INLINE Int CONSTFN operator % (const Int REF a, const Int REF b) { Int r(a); r %= b.Int::val(); return r; } INLINE Int CONSTFN operator << (const Int REF a, const Int REF b) { Int r(a); r <<= b.Int::val(); return r; } INLINE Int CONSTFN operator >> (const Int REF a, const Int REF b) { Int r(a); r >>= b.Int::val(); return r; } INLINE Int CONSTFN operator & (const Int REF a, const Int REF b) { Int r(a); r &= b.Int::val(); return r; } INLINE Int CONSTFN operator | (const Int REF a, const Int REF b) { Int r(a); r |= b.Int::val(); return r; } INLINE Int CONSTFN operator ^ (const Int REF a, const Int REF b) { Int r(a); r ^= b.Int::val(); return r; } INLINE Int CONSTFN operator + (const Int REF a, const int b) { Int r(a); r += b; return r; } INLINE Int CONSTFN operator - (const Int REF a, const int b) { Int r(a); r -= b; return r; } INLINE Int CONSTFN operator * (const Int REF a, const int b) { Int r(a); r *= b; return r; } INLINE Int CONSTFN operator / (const Int REF a, const int b) { Int r(a); r /= b; return r; } INLINE Int CONSTFN operator % (const Int REF a, const int b) { Int r(a); r %= b; return r; } INLINE Int CONSTFN operator << (const Int REF a, const int b) { Int r(a); r <<= b; return r; } INLINE Int CONSTFN operator >> (const Int REF a, const int b) { Int r(a); r >>= b; return r; } INLINE Int CONSTFN operator & (const Int REF a, const int b) { Int r(a); r &= b; return r; } INLINE Int CONSTFN operator | (const Int REF a, const int b) { Int r(a); r |= b; return r; } INLINE Int CONSTFN operator ^ (const Int REF a, const int b) { Int r(a); r ^= b; return r; } INLINE Int CONSTFN operator + (const int a, const Int REF b) { Int r(a); r += b.Int::val(); return r; } INLINE Int CONSTFN operator - (const int a, const Int REF b) { Int r(a); r -= b.Int::val(); return r; } INLINE Int CONSTFN operator * (const int a, const Int REF b) { Int r(a); r *= b.Int::val(); return r; } INLINE Int CONSTFN operator / (const int a, const Int REF b) { Int r(a); r /= b.Int::val(); return r; } INLINE Int CONSTFN operator % (const int a, const Int REF b) { Int r(a); r %= b.Int::val(); return r; } INLINE Int CONSTFN operator << (const int a, const Int REF b) { Int r(a); r <<= b.Int::val(); return r; } INLINE Int CONSTFN operator >> (const int a, const Int REF b) { Int r(a); r >>= b.Int::val(); return r; } INLINE Int CONSTFN operator & (const int a, const Int REF b) { Int r(a); r &= b.Int::val(); return r; } INLINE Int CONSTFN operator | (const int a, const Int REF b) { Int r(a); r |= b.Int::val(); return r; } INLINE Int CONSTFN operator ^ (const int a, const Int REF b) { Int r(a); r ^= b.Int::val(); return r; } #else INLINE Int CONSTFN operator - (const Int REF a) return r(a) { r.negate(); } INLINE Int CONSTFN operator ~ (const Int REF a) return r(a) { r.complement(); } INLINE Int CONSTFN operator + (const Int REF a, const Int REF b) return r(a) { r += b.Int::val(); } INLINE Int CONSTFN operator - (const Int REF a, const Int REF b) return r(a) { r -= b.Int::val(); } INLINE Int CONSTFN operator * (const Int REF a, const Int REF b) return r(a) { r *= b.Int::val(); } INLINE Int CONSTFN operator / (const Int REF a, const Int REF b) return r(a) { r /= b.Int::val(); } INLINE Int CONSTFN operator % (const Int REF a, const Int REF b) return r(a) { r %= b.Int::val(); } INLINE Int CONSTFN operator << (const Int REF a, const Int REF b) return r(a) { r <<= b.Int::val(); } INLINE Int CONSTFN operator >> (const Int REF a, const Int REF b) return r(a) { r >>= b.Int::val(); } INLINE Int CONSTFN operator & (const Int REF a, const Int REF b) return r(a) { r &= b.Int::val(); } INLINE Int CONSTFN operator | (const Int REF a, const Int REF b) return r(a) { r |= b.Int::val(); } INLINE Int CONSTFN operator ^ (const Int REF a, const Int REF b) return r(a) { r ^= b.Int::val(); } INLINE Int CONSTFN operator + (const Int REF a, const int b) return r(a) { r += b; } INLINE Int CONSTFN operator - (const Int REF a, const int b) return r(a) { r -= b; } INLINE Int CONSTFN operator * (const Int REF a, const int b) return r(a) { r *= b; } INLINE Int CONSTFN operator / (const Int REF a, const int b) return r(a) { r /= b; } INLINE Int CONSTFN operator % (const Int REF a, const int b) return r(a) { r %= b; } INLINE Int CONSTFN operator << (const Int REF a, const int b) return r(a) { r <<= b; } INLINE Int CONSTFN operator >> (const Int REF a, const int b) return r(a) { r >>= b; } INLINE Int CONSTFN operator & (const Int REF a, const int b) return r(a) { r &= b; } INLINE Int CONSTFN operator | (const Int REF a, const int b) return r(a) { r |= b; } INLINE Int CONSTFN operator ^ (const Int REF a, const int b) return r(a) { r ^= b; } INLINE Int CONSTFN operator + (const int a, const Int REF b) return r(a) { r += b.Int::val(); } INLINE Int CONSTFN operator - (const int a, const Int REF b) return r(a) { r -= b.Int::val(); } INLINE Int CONSTFN operator * (const int a, const Int REF b) return r(a) { r *= b.Int::val(); } INLINE Int CONSTFN operator / (const int a, const Int REF b) return r(a) { r /= b.Int::val(); } INLINE Int CONSTFN operator % (const int a, const Int REF b) return r(a) { r %= b.Int::val(); } INLINE Int CONSTFN operator << (const int a, const Int REF b) return r(a) { r <<= b.Int::val(); } INLINE Int CONSTFN operator >> (const int a, const Int REF b) return r(a) { r >>= b.Int::val(); } INLINE Int CONSTFN operator & (const int a, const Int REF b) return r(a) { r &= b.Int::val(); } INLINE Int CONSTFN operator | (const int a, const Int REF b) return r(a) { r |= b.Int::val(); } INLINE Int CONSTFN operator ^ (const int a, const Int REF b) return r(a) { r ^= b.Int::val(); } #endif INLINE int CONSTFN operator ! (const Int REF a) { return !a.Int::val(); } INLINE int CONSTFN operator == (const Int REF a, const Int REF b) { return a.Int::val() == b.Int::val(); } INLINE int CONSTFN operator != (const Int REF a, const Int REF b) { return a.Int::val() != b.Int::val(); } INLINE int CONSTFN operator < (const Int REF a, const Int REF b) { return a.Int::val() < b.Int::val(); } INLINE int CONSTFN operator <= (const Int REF a, const Int REF b) { return a.Int::val() <= b.Int::val(); } INLINE int CONSTFN operator > (const Int REF a, const Int REF b) { return a.Int::val() > b.Int::val(); } INLINE int CONSTFN operator >= (const Int REF a, const Int REF b) { return a.Int::val() >= b.Int::val(); } INLINE int CONSTFN operator == (const Int REF a, const int b) { return a.Int::val() == b; } INLINE int CONSTFN operator != (const Int REF a, const int b) { return a.Int::val() != b; } INLINE int CONSTFN operator < (const Int REF a, const int b) { return a.Int::val() < b; } INLINE int CONSTFN operator <= (const Int REF a, const int b) { return a.Int::val() <= b; } INLINE int CONSTFN operator > (const Int REF a, const int b) { return a.Int::val() > b; } INLINE int CONSTFN operator >= (const Int REF a, const int b) { return a.Int::val() >= b; } INLINE int CONSTFN operator == (const int a, const Int REF b) { return a == b.Int::val(); } INLINE int CONSTFN operator != (const int a, const Int REF b) { return a != b.Int::val(); } INLINE int CONSTFN operator < (const int a, const Int REF b) { return a < b.Int::val(); } INLINE int CONSTFN operator <= (const int a, const Int REF b) { return a <= b.Int::val(); } INLINE int CONSTFN operator > (const int a, const Int REF b) { return a > b.Int::val(); } INLINE int CONSTFN operator >= (const int a, const Int REF b) { return a >= b.Int::val(); } #endif #endif eturn a == b.Int::val(); } INLINE int CONSTFN operator != (const int a, const Int REF b) { return a != b.Int::val(); } INLINE int CONSTFN operator < (const int a, const Int REF b) { return a < b.Int::val(); } INLINE int CONSTFN operator <= (const int a, const Int REF b) { return a <= b.Int::val(); } INLINE int CONSTFN operator > (const int a, const Int REF b) { return a > b.Int::val(); } INLINE int CONSTFN operator >= (const ilibg++/etc/benchmarks/Makefile 600 473 0 7762 4677700001 11463 # A makefile for the stuff now in libg++/etc/benchmarks # ------ source locations # source directory for libg++.a SRCDIR = ../../../src # source include directory SRCIDIR= ../../../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< # --------------------------------------------------------------- # select QUICK= -DQUICK to get 50000 instead of 500000 iterations QUICK= -DQUICK #QUICK= all: demos tests DEMOS= builtin class virt no_nrv byval call call-var convert virt-var $(DEMOS) : Int.h Char.h dhrystone.cc demos: $(DEMOS) tests: $(DEMOS) @echo "dhrystone with builtin int and char types:" @./builtin @echo "Using classes Int and Char:" @./class @echo "Without mixed mode operators (forcing coercions):" @./convert @echo "Using by-value, rather than by-reference calling conventions:" @./byval @echo "Without using named return values:" @./no_nrv @echo "Using calls instead of inline functions:" @./call @echo "Using calls, with -fthis-is-variable:" @./call-var @echo "With all member functions virtual (non-inline):" @./virt @echo "With all member functions virtual, and -fthis-is-variable:" @./virt-var @echo "(Try other permutations/switches -- See Int.h.)" builtin: $(GXX) $(QUICK) $(GXXFLAGS) -DBUILTIN dhrystone.cc $(GXXLDFLAGS) -o builtin class: $(GXX) $(QUICK) $(GXXFLAGS) dhrystone.cc $(GXXLDFLAGS) -o class call: $(GXX) $(QUICK) $(GXXFLAGS) -DCALL dhrystone.cc $(GXXLDFLAGS) -o call call-var: $(GXX) $(QUICK) $(GXXFLAGS) -fthis-is-variable -DCALL dhrystone.cc $(GXXLDFLAGS) -o call-var convert: $(GXX) $(QUICK) $(GXXFLAGS) -DCONVERT dhrystone.cc $(GXXLDFLAGS) -o convert no_nrv: $(GXX) $(QUICK) $(GXXFLAGS) -DNO_NRV dhrystone.cc $(GXXLDFLAGS) -o no_nrv byval: $(GXX) $(QUICK) $(GXXFLAGS) -DBYVAL dhrystone.cc $(GXXLDFLAGS) -o byval virt: $(GXX) $(QUICK) $(GXXFLAGS) -DVIRT dhrystone.cc $(GXXLDFLAGS) -o virt virt-var: $(GXX) $(QUICK) $(GXXFLAGS) -fthis-is-variable -DVIRT dhrystone.cc $(GXXLDFLAGS) -o virt-var always: clean: rm -f *.o $(DEMOS) core C++.hack* XLDFLAGS) -o clibg++/etc/lf/Dirent.cc 644 473 0 3626 4677700001 10046 /* Define a portable UNIX directory-entry manipulation interface. This code is heavily based upon Doug Gwyn's public domain directory-access routines written in C. Hacked into C++ conformance for the GNU libg++ library by Douglas C. Schmidt (schmidt@ics.uci.edu). */ #include #include "Dirent.h" // error handlers void verbose_Dirent_error_handler(const char* msg) { perror(msg); errno = 0; } void quiet_Dirent_error_handler(const char*) { errno = 0; } void fatal_Dirent_error_handler(const char* msg) { perror(msg); exit(1); } one_arg_error_handler_t Dirent_error_handler = verbose_Dirent_error_handler; one_arg_error_handler_t set_Dirent_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Dirent_error_handler; Dirent_error_handler = f; return old; } #ifndef __OPTIMIZE__ /* Initialize the directory-entry control block from the given DIRNAME. Equivalent to opendir (). */ Dirent::Dirent (char *dirname) { if ((dirp = ::opendir (dirname)) == 0) (*Dirent_error_handler) ("Dirent::Dirent"); } /* Frees up the dynamically allocated buffer. */ Dirent::~Dirent (void) { ::closedir (dirp); } /* Re-initialize the directory-entry control block from the given DIRNAME. Equivalent to opendir (). */ void Dirent::opendir (char *dirname) { if ((dirp = ::opendir (dirname)) == 0) (*Dirent_error_handler) ("Dirent::Dirent"); } /* Read next entry from a directory stream. */ struct direct * Dirent::readdir (void) { return ::readdir (dirp); } /* Close a directory stream. */ void Dirent::closedir (void) { ::closedir (dirp); } /* Rewind a directory stream. */ void Dirent::rewinddir (void) { ::seekdir (dirp, long (0)); } /* Reposition a directory stream. */ void Dirent::seekdir (long loc) { ::seekdir (dirp, loc); } /* Report directory stream position. */ long Dirent::telldir (void) { return ::telldir (dirp); } #endif // __OPTIMIZE__ from a directory stream. */ struct direct * Dirent::readdir (void) { return ::readdir (dirp); } /* Cllibg++/etc/lf/Dirent.h 644 473 0 3325 4677700001 7704 /* Define a portable UNIX directory-entry manipulation interface. This code is heavily based upon Doug Gwyn's public domain directory-access routines. Hacked into C++ conformance by Doug Schmidt (schmidt@ics.uci.edu). */ #include #include #include extern "C" { #include } #ifdef rewinddir #undef rewinddir #endif class Dirent { private: DIR *dirp; public: Dirent (char *dirname); ~Dirent (void); struct direct *readdir (void); void opendir (char *filename); void closedir (void); long telldir (void); void seekdir (long loc); void rewinddir (void); }; // error handlers extern void verbose_Dirent_error_handler(char*); extern void quiet_Dirent_error_handler(char*); extern void fatal_Dirent_error_handler(char*); extern one_arg_error_handler_t Dirent_error_handler; extern one_arg_error_handler_t set_Dirent_error_handler(one_arg_error_handler_t); // OPTIMIZE #ifdef __OPTIMIZE__ inline Dirent::Dirent (char *dirname) { if ((dirp = ::opendir (dirname)) == 0) (*Dirent_error_handler) ("Dirent::Dirent"); } inline Dirent::~Dirent (void) { ::closedir (dirp); } inline void Dirent::opendir (char *dirname) { if ((dirp = ::opendir (dirname)) == 0) (*Dirent_error_handler) ("Dirent::Dirent"); } inline struct direct * Dirent::readdir (void) { return ::readdir (dirp); } inline void Dirent::closedir (void) { ::closedir (dirp); } inline void Dirent::rewinddir (void) { ::seekdir (dirp, long (0)); } inline void Dirent::seekdir (long loc) { ::seekdir (dirp, loc); } inline long Dirent::telldir (void) { return ::telldir (dirp); } #endif // __OPTIMIZE__ } inline void Dirent::opendir (char *dirname) { if ((dirp = ::opendir (dirname)) == 0) (*Dirent_error_handler) ("Dirent::Dirent"); } inline struct direct * Dirent::readdir (void) { return ::readdir (dirp); } inline void Dirent::closedir (void) { ::closedir (dirp); } inline void Direntlibg++/etc/lf/Makefile 644 473 0 7111 4677700001 7743 ############################################################################# # # Makefile for lf # # ------ source locations # source directory for libg++.a SRCDIR = ../../src # source include directory SRCIDIR= ../../g++-include # ------ installation destinations prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm -ltermcap $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< ############################################################################# # If you move this makefile, update the variable below # or else depend won't work. ############################################################################# MAKEFILE = Makefile CFILES = lf.cc entry-handler.cc screen-handler.cc option-handler.cc \ directory-handler.cc sort.cc Dirent.cc HFILES = entry-handler.h screen-handler.h option-handler.h \ directory-handler.h Dirent.h OFILES = lf.o entry-handler.o screen-handler.o option-handler.o \ directory-handler.o sort.o Dirent.o PROGRAM = lf $(PROGRAM): $(OFILES) $(GXX) $(OFILES) -o $(PROGRAM) $(GXXLDFLAGS) -ltermcap clean: rm -f *.o *.out *~ #*# core realclean: rm -f *.o *.out *~ #*# core rm -f $(PROGRAM) depend: g++dep -f $(MAKEFILE) $(CFILES) # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. Dirent.o : Dirent.cc Dirent.h directory-handler.o : directory-handler.cc Dirent.h option-handler.h \ entry-handler.h screen-handler.h directory-handler.h entry-handler.o : entry-handler.cc entry-handler.h screen-handler.h lf.o : lf.cc option-handler.h screen-handler.h directory-handler.h \ entry-handler.h option-handler.o : option-handler.cc option-handler.h screen-handler.o : screen-handler.cc screen-handler.h sort.o : sort.cc # IF YOU PUT ANYTHING HERE IT WILL GO AWAY LINE, IT WILL GO AWAY. Dirent.o : Dirent.cc Dirent.h directory-handler.o : directory-handler.cc Dirent.h option-handler.h \ entry-handler.h screen-handler.h directory-handler.h entry-handler.o : entry-handler.cc entry-handler.h screen-handler.h lf.o : lf.cc option-handler.h screen-handler.h directory-handler.h \ entry-handler.h option-handler.o : option-handler.cc option-handler.h screen-handler.o : screen-handler.cc screen-libg++/etc/lf/directory-hand 644 473 0 2042 4677700001 11140 // This may look like C code, but it is really -*- C++ -*- /* Manipulate all directory entries for all file classes. */ #pragma once #include "entry-handler.h" class Directory_Handler { public: /* There are five major types of files in the UNIX system. */ enum file_types { DIRS, /* Subdirectories. */ FILES, /* Regular files. */ EXECS, /* Executable files. */ DLINKS, /* Directory links (if -l option is enabled). */ FLINKS, /* File links (if -l option is enabled). */ LINKS, /* File *and* directory links (if -l option is *not* enabled). */ MAX_TYPES, }; Directory_Handler (void); /* Formats the current directory files. */ void print (void); /* Lists the current directory files. */ private: /* static */ Entry_Handler file_class[MAX_TYPES]; /* File class array. */ static char *class_name[MAX_TYPES]; /* String naem for each file class. */ }; /* File links (if -l option is enabled). */ LINKS, /* File *and* directory links (if -l option is *not* enabled). */ MAX_TYPES, }; Directory_Handler (void); /* Formats the current directory files. */ void print (void); /* Lists the current directory files. */ private: /* static */ Entry_Handler file_class[MAX_TYPES]; /* File class array. */ static char *class_name[MAX_TYPES]; /* String naemlibg++/etc/lf/entry-handler. 644 473 0 3512 4677700002 11062 // This may look like C code, but it is really -*- C++ -*- /* Manipulate directory entries of a particular file class. */ #pragma once #include #include #include "screen-handler.h" /* Defined in sort.cc. */ void sort (char **base_ptr, int total_elems); class Entry_Handler { private: static const int default_entries; /* Initial number of file entries per class. */ int max_entry_length; /* Size of largest filename. */ int total_entries; /* Total number of filenames. */ int entries; /* Current number of filenames. */ char **buf; /* Buffer containing filenames for this file class. */ public: Entry_Handler (void); /* Initialize a new file class. */ int entry_number (void); /* Current number of entries. */ void add_entry (char *entry_name, int length); /* Add an entry to the class. */ void sort_entries (void); /* Sort entries by filename. */ void print_entries (char *class_name); /* Print file entries. */ }; /* See comments in the .cc file for the following inline functions */ #ifdef __OPTIMIZE__ inline Entry_Handler::Entry_Handler (void) { entries = max_entry_length = 0; total_entries = default_entries; buf = new char *[default_entries]; } inline int Entry_Handler::entry_number (void) { return entries; } inline void Entry_Handler::add_entry (char *entry_name, int length) { if (entries >= total_entries) buf = new {buf, total_entries *= 2} char *; max_entry_length >?= length; buf[entries++] = strcpy (new char[length + 1], entry_name); } inline void Entry_Handler::sort_entries (void) { sort (buf, entries); } #endif // __OPTIMIZE__ x_entry_length = 0; total_entries = default_entries; buf = new char *[default_entries]; } inline int Entry_Handler::entry_number (void) { return entries; } inline void Entrlibg++/etc/lf/lf.cc 644 473 0 1070 4677700002 7212 /* Driver program for directory listing facility. */ /* Type the -h option for program usage information. */ #include "option-handler.h" #include "screen-handler.h" #include "directory-handler.h" /* Manages program options, globally visible to other modules. */ Option_Handler option; /* Initializes the screen object. */ Screen_Handler screen; /* Set the program options and turn over the dirty work to the main directory handling module. */ int main (int argc, char *argv[]) { option (argc, argv); Directory_Handler files; files.print (); return 0; } Type the -h option for program usage information. */ #include "option-handler.h" #include "screen-handler.h" #include "directory-handler.h" /* Manages program options, globally visible to other modules. */ Option_Handler option; /* Initializes the screen object. */ Screen_Handler screen; /* Set the program options and turn over the dirty work to the main directory handling module. */ int main (int argc, char *argv[]) { option (argc, argv); Dlibg++/etc/lf/option-handler 644 473 0 2020 4677700002 11144 // This may look like C code, but it is really -*- C++ -*- #pragma once /* Process directory listing program options. */ /* Enumeration of all directory listing options. */ enum option_type { HIDDEN = 01, /* Print hidden files (those beginning with '.') */ LINK = 02, /* Distinguish between directory and file links. */ }; class Option_Handler { private: static unsigned option_word; /* Compact bitwise-storage for program options. */ static char *program_name; /* Name of listing program. */ static void usage (void); /* Prints usage then exits. */ public: Option_Handler (void); /* Initialize options. */ void operator() (int argc, char *argv[]); /* Process command-line options. */ int operator[] (option_type option); /* Check if option is enabled. */ }; /* Speed things up a bit if we're optimizing. */ #ifdef __OPTIMIZE__ inline int Option_Handler::operator[] (option_type option) { return option_word & option; } #endif // __OPTIMIZE__ usage (void); /* Prints usage then exits. */ public: Option_Handler (void); /* Initialize options. */ void operator() (int argc, char *argv[]); /* Process command-line options. */ int operator[] (option_type option); /* Check if option is enabled. */ }; /* Speed things up a bit if we're optimizing. */ #ifdef __OPTIMIZE__ inline int Option_Handler::operator[] (option_type option) { return option_word & option; } #endif libg++/etc/lf/screen-handler 644 473 0 3304 4677700003 11122 // This may look like C code, but it is really -*- C++ -*- #pragma once #include #include /* Handles necessary screen-manipultations. */ class Screen_Handler { private: static char term_entry[1024]; /* Holds termcap entry for current terminal. */ static char temp_buf[100]; /* Holds inverse screen attributes. */ static int width; /* Current screen width, needed to format output. */ static char *current_ptr; /* Pointer to current position in temp_buf. */ static char *inverse_start; /* Control sequence beginning inverse mode. */ static char *inverse_end; /* Control sequence ending inverse mode. */ static void center (char *buf); /* Prints out leading spaces to center BUF. */ static int fputchar (int i); /* Prints a character to standard output. */ public: Screen_Handler (void); /* Initialize the screen width. */ static int screen_width (void); /* Return current screen width. */ static void print_inverse_centered (char *buf); /* Centers, inverts, and prints BUF. */ }; /* See comments in .cc file for inline functions. */ #ifdef __OPTIMIZE__ inline int Screen_Handler::screen_width (void) { return width; } inline int Screen_Handler::fputchar (int i) { putchar (i); } inline void Screen_Handler::center (char *buf) { int offset; int len = strlen (buf); offset = width - len >> 1; for (int i = 0; i < offset; i++) putchar (' '); } inline void Screen_Handler::print_inverse_centered (char *buf) { putchar ('\n'); center (buf); tputs (inverse_start, 1, fputchar); printf ("%s\n\n", buf); tputs (inverse_end, 1, fputchar); } #endif // __OPTIMIZE__ een_width (void) { return width; } inline int Screen_Handler::fputchar (int i) { putchar (i); } inline void Screen_Handler::center (char *buf) { int offset; int len = strlen (buf); offset = width - len >> 1; for (int i = 0; i < offset; i++) putchar (' '); } inline void Screen_Handler::prlibg++/etc/lf/sort.cc 644 473 0 12652 4677700003 7631 #include #include #include /* the next 6 #defines implement a very fast in-line stack abstraction */ #define MAX_STACK_SIZE 32 #define DISPOSE_STACK(S) (free(S)) #define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0) #define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0) #define STACK_NOT_EMPTY (stack < top) #define SWAP(A,B) do {char *_temp = (A);(A) = (B);(B) = _temp;} while (0) /* Discontinue quicksort algorithm when partition gets below this size. This particular magic number was chosen to work best on a Sun 4/260. */ #define MAX_THRESH 30 /* Data structure for stack of unfulfilled obligations. */ typedef struct { char **lo; char **hi; } stack_node; /* Once main array is partially sorted by quicksort the remainder is completely sorted using insertion sort, since this is efficient for partitions below MAX_THRESH size. BASE points to the beginning of the array to sort, and END_PTR points at the very last element in the array (*not* one beyond it!). */ inline static void insert_sort (char **base_ptr, char **end_ptr) { char **run_ptr; char **tmp_ptr = base_ptr; char **thresh = end_ptr > 1); if (strcmp (*middle, *low) < 0) SWAP (*middle, *low); if (strcmp (*high, *middle) < 0) SWAP (*middle, *high); else return *middle; if (strcmp (*middle, *low) < 0) SWAP (*middle, *low); return *middle; } /* Order elements using quicksort. This implementation incorporates 4 optimizations discussed in Sedgewick: 1. Non-recursive, using an explicit stack of log (n) pointers that indicate the next array partition to sort. 2. Choses the pivot element to be the median-of-three, reducing the probability of selecting a bad pivot value. 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion sort to sort within the partitions. This is a big win, since insertion sort is faster for small, mostly sorted array segements. 4. The larger of the 2 sub-partitions are always pushed onto the stack first, with the algorithm then concentrating on the smaller partition. This *guarantees* no more than log (n) stack size is needed! */ void sort (char **base_ptr, int total_elems) { if (total_elems > MAX_THRESH) { char **lo = base_ptr; char **hi = lo + (total_elems - 1); char **left_ptr; char **right_ptr; stack_node stack[MAX_STACK_SIZE]; stack_node *top = stack + 1; while (STACK_NOT_EMPTY) { /* Select the median-of-three here. This allows us to skip forward for the LEFT_PTR and RIGHT_PTR. */ char *pivot = find_pivot (lo, hi); left_ptr = lo + 1; right_ptr = hi - 1; /* Here's the famous ``collapse the walls'' section of quicksort. Gotta like those tight inner loops! */ do { while (strcmp (*left_ptr, pivot) < 0) left_ptr++; while (strcmp (pivot, *right_ptr) < 0) right_ptr--; if (left_ptr < right_ptr) { SWAP (*left_ptr, *right_ptr); left_ptr++; right_ptr--; } else if (left_ptr == right_ptr) { left_ptr++; right_ptr--; break; } } while (left_ptr <= right_ptr); if ((right_ptr - lo) <= MAX_THRESH) { if ((hi - left_ptr) <= MAX_THRESH) /* ignore both small tables */ POP (lo, hi); else /* ignore small left table */ lo = left_ptr; } else if ((hi - left_ptr) <= MAX_THRESH) /* ignore small right table */ hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) { /* push larger left table */ PUSH (lo, right_ptr); lo = left_ptr; } else { /* push larger right table */ PUSH (left_ptr, hi); hi = right_ptr; } } } insert_sort (base_ptr, base_ptr + (total_elems - 1)); } left_ptr) <= MAX_THRESH) /* ignore small right table */ hi = right_ptr; libg++/etc/c++-mode.el 600 473 0 106346 4677700004 7563 ;; C++ code editing commands for Emacs ;; 1987 Dave Detlefs (dld@cs.cmu.edu) ;; and Stewart Clamen (clamen@cs.cmu.edu). ;; Done by fairly faithful modification of: ;; c-mode.el, Copyright (C) 1985 Richard M. Stallman. ;; ;; Feb, 1990 (Dave Detlefs, dld@cs.cmu.edu) ;; Fixed electric-c++-terminator to handle double colons, at the ;; request of John Hagerman. ;; ;; Jan, 1990 (Doug Lea, dl@oswego.edu) ;; Replaced c++-comment-region and c++-uncomment-region with ;; versions from Igor Metz that avoid potential infinite loops. ;; ;; Oct, 1989 (Dave Detlefs, dld@cs.cmu.edu) ;; Added contribution from Igor Metz : ;; functions c++-comment-region and c++-uncomment-region and ;; corresponding key-binding. ;; Also fixed bug in indentation of second line after an empty ;; arglist with empty-arglist non-null. ;; ;; Sept, 1989 (Glen Ditchfield, gjditchfield@violet.uwaterloo.ca): ;; Textual changes to more closely imitate Emacs 18.55's c-mode. ;; Fixed handling of "default:", where ":" was the last character in the ;; buffer. Fixed indentation of comments starting in column 0, and when ;; previous line contained more than one comment start string. Fixed ;; handling of "friend class". ;; ;; Aug 7, 1989; John Hagerman (hagerman@ece.cmu.edu): ;; Changed calculate-c++-indent to handle member initializations ;; more flexibly. Two new variables are used to control behavior: ;; c++-member-init-indent and c++-continued-member-init-offset. ;; Note the assumption that member initializations and argument ;; declarations are not mixed in one function definition. ;; ;; June 1989 (Dave Detlefs, dld@cs.cmu.edu) ;; Fixed calculate-c++-indent to handle continued lines ending in ;; {'s. (I wasn't following C-mode closely enough, or C-mode ;; changed.) Made ' a quote character, at the behest of someone ;; whose mail I apparently deleted (if they send me mail I'll credit ;; them here in a future revision.) ;; Dan Weinreb (dlw@odi.com) pointed out that 'c++-mode successively ;; bound c++-indent-exp and c++-indent-defun to ESC-^q. ESC-^q is ;; now bound to c++-indent-exp, while, c++-indent-defun is invoked ;; with ESC-^x. ;; February 1989 (Dave Detlefs, dld@cs.cmu.edu) ;; Fixed some errors in c++-indent-defun, as pointed out by Sam ;; Haradhvala (odi!sam@talcott.harvard.edu). ;; October 1988 (Dave Detlefs, dld@cs.cmu.edu) ;; It turns out I had only *thought* I had made ;; beginning(end)-of-defun work. It should work better now -- you ;; can either attempt to match defun headers "strongly," using a ;; very complicated regexp, or "weakly," using a simple one. This ;; is settable by a variable; the default is the cheaper weak ;; method. (Stewart Clamen was intimately involved in this, too.) ;; ;; I made "'" *not* be a string delimiter, because that was causing ;; comments containing contractions to ("// don't") to mess up paren ;; balancing. ;; ;; I also incorporated another slight indentation fix from Glen ;; Ditchfield. ;; ;; We hope this is will make into version 19 of gnu-emacs. ;; ;; September 1988: incorporated changes from Fred Calm at Schlumberger. ;; Also, made beginning(end)-of-defun, indent-defun work. ;; ;; August 1987: incorporated changes done by Glen Ditchfield of Waterloo. (defvar c++-mode-abbrev-table nil "Abbrev table in use in C++-mode buffers.") (define-abbrev-table 'c++-mode-abbrev-table ()) (defvar c++-mode-map () "Keymap used in C++ mode.") (if c++-mode-map () (setq c++-mode-map (make-sparse-keymap)) (define-key c++-mode-map "\C-j" 'reindent-then-newline-and-indent) (define-key c++-mode-map "{" 'electric-c++-brace) (define-key c++-mode-map "}" 'electric-c++-brace) (define-key c++-mode-map ";" 'electric-c++-semi) (define-key c++-mode-map "\e\C-h" 'mark-c-function) (define-key c++-mode-map "\e\C-q" 'indent-c++-exp) (define-key c++-mode-map "\177" 'backward-delete-char-untabify) (define-key c++-mode-map "\t" 'c++-indent-command) (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header) (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region) (define-key c++-mode-map "\C-c\C-c" 'c++-comment-region) (define-key c++-mode-map "\C-c\C-u" 'c++-uncomment-region) (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun) (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun) (define-key c++-mode-map "\e\C-x" 'c++-indent-defun)) (defvar c++-mode-syntax-table nil "Syntax table in use in C++-mode buffers.") (if c++-mode-syntax-table () (setq c++-mode-syntax-table (copy-syntax-table c-mode-syntax-table)) (modify-syntax-entry ?/ ". 12" c++-mode-syntax-table) (modify-syntax-entry ?\n ">" c++-mode-syntax-table) (modify-syntax-entry ?\' "." c++-mode-syntax-table)) (defvar c++-continued-member-init-offset nil "*Extra indent for continuation lines of member inits; NIL means to align with previous initializations rather than with the colon on the first line.") (defvar c++-member-init-indent 0 "*Indentation level of member initializations in function declarations.") (defvar c++-friend-offset -4 "*Offset of C++ friend class declarations relative to member declarations.") (defvar c++-electric-colon t "*If t, colon is an electric terminator.") (defvar c++-empty-arglist-indent nil "*Indicates how far to indent an line following an empty argument list. Nil indicates to just after the paren.") (defun c++-mode () "Major mode for editing C++ code. Very much like editing C code. Expression and list commands understand all C++ brackets. Tab at left margin indents for C++ code Comments are delimited with /* ... */ {or with // ... } Paragraphs are separated by blank lines only. Delete converts tabs to spaces as it moves back. \\{c++-mode-map} Variables controlling indentation style: c-tab-always-indent Non-nil means TAB in C mode should always reindent the current line, regardless of where in the line point is when the TAB command is used. Default is t. c-auto-newline Non-nil means automatically newline before and after braces, and after colons and semicolons, inserted in C code. c-indent-level Indentation of C statements within surrounding block. The surrounding block's indentation is the indentation of the line on which the open-brace appears. c-continued-statement-offset Extra indentation given to a substatement, such as the then-clause of an if or body of a while. c-continued-brace-offset Extra indentation given to a brace that starts a substatement. This is in addition to c-continued-statement-offset. c-brace-offset Extra indentation for line if it starts with an open brace. c-brace-imaginary-offset An open brace following other text is treated as if it were this far to the right of the start of its line. c-argdecl-indent Indentation level of declarations of C function arguments. c-label-offset Extra indentation for line that is a label, or case or ``default:'', or ``public:'' or ``private:'', or ``protected:''. c++-electric-colon If non-nil at invocation of c++-mode (t is the default) colon electricly indents. c++-empty-arglist-indent If non-nil, a function declaration or invocation which ends a line with a left paren is indented this many extra spaces, instead of flush with the left paren. c++-friend-offset Offset of C++ friend class declarations relative to member declarations. c++-member-init-indent Indentation level of member initializations in function declarations, if they are on a separate line beginning with a colon. c++-continued-member-init-offset Extra indentation for continuation lines of member initializations; NIL means to align with previous initializations rather than with the colon. Settings for K&R, BSD, and Stroustrup indentation styles are c-indent-level 5 8 4 c-continued-statement-offset 5 8 4 c-continued-brace-offset 0 c-brace-offset -5 -8 0 c-brace-imaginary-offset 0 c-argdecl-indent 0 8 4 c-label-offset -5 -8 -4 c++-empty-arglist-indent 4 c++-friend-offset 0 Turning on C++ mode calls the value of the variable c++-mode-hook with no args,if that value is non-nil." (interactive) (kill-all-local-variables) (use-local-map c++-mode-map) (setq major-mode 'c++-mode) (setq mode-name "C++") (setq local-abbrev-table c++-mode-abbrev-table) (set-syntax-table c++-mode-syntax-table) (make-local-variable 'paragraph-start) (setq paragraph-start (concat "^$\\|" page-delimiter)) (make-local-variable 'paragraph-separate) (setq paragraph-separate paragraph-start) (make-local-variable 'paragraph-ignore-fill-prefix) (setq paragraph-ignore-fill-prefix t) (make-local-variable 'indent-line-function) (setq indent-line-function 'c++-indent-line) (make-local-variable 'require-final-newline) (setq require-final-newline t) (make-local-variable 'comment-start) (setq comment-start "// ") (make-local-variable 'comment-end) (setq comment-end "") (make-local-variable 'comment-column) (setq comment-column 32) (make-local-variable 'comment-start-skip) (setq comment-start-skip "/\\*+ *\\|// *") (make-local-variable 'comment-indent-hook) (setq comment-indent-hook 'c++-comment-indent) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments nil) (run-hooks 'c++-mode-hook) (if c++-electric-colon (define-key c++-mode-map ":" 'electric-c++-terminator))) ;; This is used by indent-for-comment ;; to decide how much to indent a comment in C++ code ;; based on its context. (defun c++-comment-indent () (if (looking-at "^\\(/\\*\\|//\\)") 0 ;Existing comment at bol stays there. (save-excursion (skip-chars-backward " \t") (max ;; leave at least one space on non-empty lines. (if (zerop (current-column)) 0 (1+ (current-column))) (let ((cur-pt (point))) (beginning-of-line 0) ;; If previous line had a comment, use it's indent (if (re-search-forward comment-start-skip cur-pt t) (progn (goto-char (match-beginning 0)) (current-column)) comment-column)))))) ;otherwise indent at comment column. (defun electric-c++-brace (arg) "Insert character and correct line's indentation." (interactive "P") (let (insertpos) (if (and (not arg) (eolp) (or (save-excursion (skip-chars-backward " \t") (bolp)) (if c-auto-newline (progn (c++-indent-line) (newline) t) nil))) (progn (insert last-command-char) (c++-indent-line) (if c-auto-newline (progn (newline) ;; (newline) may have done auto-fill (setq insertpos (- (point) 2)) (c++-indent-line))) (save-excursion (if insertpos (goto-char (1+ insertpos))) (delete-char -1)))) (if insertpos (save-excursion (goto-char insertpos) (self-insert-command (prefix-numeric-value arg))) (self-insert-command (prefix-numeric-value arg))))) (defun electric-c++-semi (arg) "Insert character and correct line's indentation." (interactive "P") (if c-auto-newline (electric-c++-terminator arg) (self-insert-command (prefix-numeric-value arg)))) (defun electric-c++-terminator (arg) "Insert character and correct line's indentation." (interactive "P") (let (insertpos (end (point))) (if (and (not arg) (eolp) (not (save-excursion (beginning-of-line) (skip-chars-forward " \t") (or (= (following-char) ?#) ;; Colon is special only after a label, or ;; case, or another colon. ;; So quickly rule out most other uses of colon ;; and do no indentation for them. (and (eq last-command-char ?:) (not (looking-at "case[ \t]")) (save-excursion (forward-word 1) (skip-chars-forward " \t") (< (point) end)) ;; Do re-indent double colons (save-excursion (end-of-line 1) (looking-at ":"))) (progn (beginning-of-defun) (let ((pps (parse-partial-sexp (point) end))) (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) (progn (insert last-command-char) (c++-indent-line) (and c-auto-newline (not (c-inside-parens-p)) (progn ;; the new marker object, used to be just an integer (setq insertpos (make-marker)) ;; changed setq to set-marker (set-marker insertpos (1- (point))) ;; do this before the newline, since in auto fill can break (newline) (c-indent-line))) (save-excursion (if insertpos (goto-char (1+ insertpos))) (delete-char -1)))) (if insertpos (save-excursion (goto-char insertpos) (self-insert-command (prefix-numeric-value arg))) (self-insert-command (prefix-numeric-value arg))))) (defun c++-indent-command (&optional whole-exp) "Indent current line as C++ code, or in some cases insert a tab character. If c-tab-always-indent is non-nil (the default), always indent current line. Otherwise, indent the current line only if point is at the left margin or in the line's indentation; otherwise insert a tab. A numeric argument, regardless of its value, means indent rigidly all the lines of the expression starting after point so that this line becomes properly indented. The relative indentation among the lines of the expression are preserved." (interactive "P") (if whole-exp ;; If arg, always indent this line as C ;; and shift remaining lines of expression the same amount. (let ((shift-amt (c++-indent-line)) beg end) (save-excursion (if c-tab-always-indent (beginning-of-line)) (setq beg (point)) (forward-sexp 1) (setq end (point)) (goto-char beg) (forward-line 1) (setq beg (point))) (if (> end beg) (indent-code-rigidly beg end shift-amt "#"))) (if (and (not c-tab-always-indent) (save-excursion (skip-chars-backward " \t") (not (bolp)))) (insert-tab) (c++-indent-line)))) (defun c++-indent-line () "Indent current line as C++ code. Return the amount the indentation changed by." (let ((indent (calculate-c++-indent nil)) beg shift-amt (case-fold-search nil) (pos (- (point-max) (point)))) (beginning-of-line) (setq beg (point)) (cond ((eq indent nil) (setq indent (current-indentation))) ((eq indent t) (setq indent (calculate-c-indent-within-comment))) ((looking-at "[ \t]*#") (setq indent 0)) (t (skip-chars-forward " \t") (if (listp indent) (setq indent (car indent))) (cond ((looking-at "\\(default\\|public\\|private\\|protected\\):") (setq indent (+ indent c-label-offset))) ((or (looking-at "case\\b") (and (looking-at "[A-Za-z]") (save-excursion (forward-sexp 1) (looking-at ":[^:]")))) (setq indent (max 1 (+ indent c-label-offset)))) ((and (looking-at "else\\b") (not (looking-at "else\\s_"))) (setq indent (save-excursion (c-backward-to-start-of-if) (current-indentation)))) ((looking-at "friend\[ \t]class[ \t]") (setq indent (+ indent c++-friend-offset))) ((= (following-char) ?}) (setq indent (- indent c-indent-level))) ((= (following-char) ?{) (setq indent (+ indent c-brace-offset)))))) (skip-chars-forward " \t") (setq shift-amt (- indent (current-column))) (if (zerop shift-amt) (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos))) (delete-region beg (point)) (indent-to indent) ;; If initial point was within line's indentation, ;; position after the indentation. Else stay at same point in text. (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos)))) shift-amt)) (defun calculate-c++-indent (&optional parse-start) "Return appropriate indentation for current line as C++ code. In usual case returns an integer: the column to indent to. Returns nil if line starts inside a string, t if in a comment." (save-excursion (beginning-of-line) (let ((indent-point (point)) (case-fold-search nil) state containing-sexp) (if parse-start (goto-char parse-start) (beginning-of-defun)) (while (< (point) indent-point) (setq parse-start (point)) (setq state (parse-partial-sexp (point) indent-point 0)) (setq containing-sexp (car (cdr state)))) (cond ((or (nth 3 state) (nth 4 state)) ;; return nil or t if should not change this line (nth 4 state)) ((null containing-sexp) ;; Line is at top level. May be data or function definition, or ;; may be function argument declaration or member initialization. ;; Indent like the previous top level line unless ;; (1) the previous line ends in a closeparen without semicolon, ;; in which case this line is the first argument declaration or ;; member initialization, or ;; (2) the previous line begins with a colon, ;; in which case this is the second line of member inits. ;; It is assumed that arg decls and member inits are not mixed. (goto-char indent-point) (skip-chars-forward " \t") (if (= (following-char) ?{) 0 ; Unless it starts a function body (c++-backward-to-noncomment (or parse-start (point-min))) (if (= (preceding-char) ?\)) (progn ; first arg decl or member init (goto-char indent-point) (skip-chars-forward " \t") (if (= (following-char) ?:) c++-member-init-indent c-argdecl-indent)) (if (= (preceding-char) ?\;) (backward-char 1)) (if (= (preceding-char) ?}) 0 (beginning-of-line) ; continued arg decls or member inits (skip-chars-forward " \t") (if (= (following-char) ?:) (if c++-continued-member-init-offset (+ (current-indentation) c++-continued-member-init-offset) (progn (forward-char 1) (skip-chars-forward " \t") (current-column))) (current-indentation))) ))) ((/= (char-after containing-sexp) ?{) ;; line is expression, not statement: ;; indent to just after the surrounding open -- unless ;; empty arg list, in which case we do what ;; c++-empty-arglist-indent says to do. (if (and c++-empty-arglist-indent (or (null (nth 2 state)) ;; indicates empty arg ;; list. ;; Use a heuristic: if the first ;; non-whitespace following left paren on ;; same line is not a comment, ;; is not an empty arglist. (save-excursion (goto-char (1+ containing-sexp)) (not (looking-at "\\( \\|\t\\)*[^/\n]"))))) (progn (goto-char containing-sexp) (beginning-of-line) (skip-chars-forward " \t") (goto-char (min (+ (point) c++-empty-arglist-indent) (1+ containing-sexp))) (current-column)) ;; In C-mode, we would always indent to one after the ;; left paren. Here, though, we may have an ;; empty-arglist, so we'll indent to the min of that ;; and the beginning of the first argument. (goto-char (1+ containing-sexp)) (current-column))) (t ;; Statement. Find previous non-comment character. (goto-char indent-point) (c++-backward-to-noncomment containing-sexp) (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?\{))) ;; This line is continuation of preceding line's statement; ;; indent c-continued-statement-offset more than the ;; previous line of the statement. (progn (c-backward-to-start-of-continued-exp containing-sexp) (+ c-continued-statement-offset (current-column))) ;; This line starts a new statement. ;; Position following last unclosed open. (goto-char containing-sexp) ;; Is line first statement after an open-brace? (or ;; If no, find that first statement and indent like it. (save-excursion (forward-char 1) (while (progn (skip-chars-forward " \t\n") (looking-at (concat "#\\|/\\*\\|//" "\\|case[ \t]" "\\|[a-zA-Z0-9_$]*:[^:]" "\\|friend[ \t]class[ \t]"))) ;; Skip over comments and labels following openbrace. (cond ((= (following-char) ?\#) (forward-line 1)) ((looking-at "/\\*") (search-forward "*/" nil 'move)) ((looking-at "//\\|friend[ \t]class[ \t]") (forward-line 1)) (t (re-search-forward ":[^:]" nil 'move)))) ;; The first following code counts ;; if it is before the line we want to indent. (and (< (point) indent-point) (current-column))) ;; If no previous statement, ;; indent it relative to line brace is on. ;; For open brace in column zero, don't let statement ;; start there too. If c-indent-offset is zero, ;; use c-brace-offset + c-continued-statement-offset instead. ;; For open-braces not the first thing in a line, ;; add in c-brace-imaginary-offset. (+ (if (and (bolp) (zerop c-indent-level)) (+ c-brace-offset c-continued-statement-offset) c-indent-level) ;; Move back over whitespace before the openbrace. ;; If openbrace is not first nonwhite thing on the line, ;; add the c-brace-imaginary-offset. (progn (skip-chars-backward " \t") (if (bolp) 0 c-brace-imaginary-offset)) ;; If the openbrace is preceded by a parenthesized exp, ;; move to the beginning of that; ;; possibly a different line (progn (if (eq (preceding-char) ?\)) (forward-sexp -1)) ;; Get initial indentation of the line we are on. (current-indentation)))))))))) (defun c++-backward-to-noncomment (lim) (let (opoint stop) (while (not stop) (skip-chars-backward " \t\n\r\f" lim) (setq opoint (point)) (cond ((and (>= (point) (+ 2 lim)) (save-excursion (forward-char -2) (looking-at "\\*/"))) (search-backward "/*" lim 'move)) ((and (search-backward "//" (max (point-bol) lim) 'move) (not (within-string-p (point) opoint)))) (t (beginning-of-line) (skip-chars-forward " \t") (if (looking-at "#") (setq stop (<= (point) lim)) (setq stop t) (goto-char opoint))))))) (defun indent-c++-exp () "Indent each line of the C++ grouping following point." (interactive) (let ((indent-stack (list nil)) (contain-stack (list (point))) (case-fold-search nil) restart outer-loop-done inner-loop-done state ostate this-indent last-sexp at-else at-brace (opoint (point)) (next-depth 0)) (save-excursion (forward-sexp 1)) (save-excursion (setq outer-loop-done nil) (while (and (not (eobp)) (not outer-loop-done)) (setq last-depth next-depth) ;; Compute how depth changes over this line ;; plus enough other lines to get to one that ;; does not end inside a comment or string. ;; Meanwhile, do appropriate indentation on comment lines. (setq innerloop-done nil) (while (and (not innerloop-done) (not (and (eobp) (setq outer-loop-done t)))) (setq ostate state) (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) nil nil state)) (setq next-depth (car state)) (if (and (car (cdr (cdr state))) (>= (car (cdr (cdr state))) 0)) (setq last-sexp (car (cdr (cdr state))))) (if (or (nth 4 ostate)) (c++-indent-line)) (if (or (nth 3 state)) (forward-line 1) (setq innerloop-done t))) (if (<= next-depth 0) (setq outer-loop-done t)) (if outer-loop-done nil ;; If this line had ..))) (((.. in it, pop out of the levels ;; that ended anywhere in this line, even if the final depth ;; doesn't indicate that they ended. (while (> last-depth (nth 6 state)) (setq indent-stack (cdr indent-stack) contain-stack (cdr contain-stack) last-depth (1- last-depth))) (if (/= last-depth next-depth) (setq last-sexp nil)) ;; Add levels for any parens that were started in this line. (while (< last-depth next-depth) (setq indent-stack (cons nil indent-stack) contain-stack (cons nil contain-stack) last-depth (1+ last-depth))) (if (null (car contain-stack)) (setcar contain-stack (or (car (cdr state)) (save-excursion (forward-sexp -1) (point))))) (forward-line 1) (skip-chars-forward " \t") (if (eolp) nil (if (and (car indent-stack) (>= (car indent-stack) 0)) ;; Line is on an existing nesting level. ;; Lines inside parens are handled specially. (if (/= (char-after (car contain-stack)) ?{) (setq this-indent (car indent-stack)) ;; Line is at statement level. ;; Is it a new statement? Is it an else? ;; Find last non-comment character before this line (save-excursion (setq at-else (looking-at "else\\W")) (setq at-brace (= (following-char) ?{)) (c++-backward-to-noncomment opoint) (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) ;; Preceding line did not end in comma or semi; ;; indent this line c-continued-statement-offset ;; more than previous. (progn (c-backward-to-start-of-continued-exp (car contain-stack)) (setq this-indent (+ c-continued-statement-offset (current-column) (if at-brace c-continued-brace-offset 0)))) ;; Preceding line ended in comma or semi; ;; use the standard indent for this level. (if at-else (progn (c-backward-to-start-of-if opoint) (setq this-indent (current-indentation))) (setq this-indent (car indent-stack)))))) ;; Just started a new nesting level. ;; Compute the standard indent for this level. (let ((val (calculate-c++-indent (if (car indent-stack) (- (car indent-stack)))))) (setcar indent-stack (setq this-indent val)))) ;; Adjust line indentation according to its contents (if (looking-at "\\(public\\|private\\|protected\\):") (setq this-indent (- this-indent c-indent-level))) (if (or (looking-at "case[ \t]") (and (looking-at "[A-Za-z]") (save-excursion (forward-sexp 1) (looking-at ":[^:]")))) (setq this-indent (max 1 (+ this-indent c-label-offset)))) (if (looking-at "friend[ \t]class[ \t]") (setq this-indent (+ this-indent c++-friend-offset))) (if (= (following-char) ?}) (setq this-indent (- this-indent c-indent-level))) (if (= (following-char) ?{) (setq this-indent (+ this-indent c-brace-offset))) ;; Put chosen indentation into effect. (or (= (current-column) this-indent) (= (following-char) ?\#) (progn (delete-region (point) (progn (beginning-of-line) (point))) (indent-to this-indent))) ;; Indent any comment following the text. (or (looking-at comment-start-skip) (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t) (progn (indent-for-comment) (beginning-of-line))))))))) ) (defun fill-C-comment () (interactive) (save-excursion (let ((save fill-prefix)) (beginning-of-line 1) (save-excursion (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t) (goto-char (match-end 0)) (set-fill-prefix)) (while (looking-at fill-prefix) (previous-line 1)) (next-line 1) (insert-string "\n") (fill-paragraph nil) (delete-char -1) (setq fill-prefix save)))) (defun point-bol () "Returns the value of the point at the beginning of the current line." (save-excursion (beginning-of-line) (point))) (defun c++-insert-header () "Insert header denoting C++ code at top of buffer." (interactive) (save-excursion (goto-char (point-min)) (insert "// " "This may look like C code, but it is really " "-*- C++ -*-" "\n\n"))) (defun within-string-p (point1 point2) "Returns true if number of double quotes between two points is odd." (let ((s (buffer-substring point1 point2))) (not (zerop (mod (count-char-in-string ?\" s) 2))))) (defun count-char-in-string (c s) (let ((count 0) (pos 0)) (while (< pos (length s)) (setq count (+ count (if (\= (aref s pos) c) 1 0))) (setq pos (1+ pos))) count)) ;;; This page covers "macroization;" making C++ parameterized types ;;; via macros. (defvar c++-default-macroize-column 78 "Place to insert backslashes.") (defun c++-macroize-region (from to arg) "Insert backslashes at end of every line in region. Useful for defining cpp macros. If called with negative argument, will remove trailing backslashes, so that indentation will work right." (interactive "r\np") (save-excursion (goto-char from) (beginning-of-line 1) (let ((line (count-lines (point-min) (point))) (to-line (save-excursion (goto-char to) (count-lines (point-min) (point))))) (while (< line to-line) (backslashify-current-line (> arg 0)) (next-line 1) (setq line (1+ line)))))) (defun backslashify-current-line (doit) (end-of-line 1) (cond (doit ;; Note that "\\\\" is needed to get one backslash. (if (not (save-excursion (forward-char -1) (looking-at "\\\\"))) (progn (if (>= (current-column) c++-default-macroize-column) (insert " \\") (while (<= (current-column) c++-default-macroize-column) (insert "\t") (end-of-line)) (delete-char -1) (while (< (current-column) c++-default-macroize-column) (insert " ") (end-of-line)) (insert "\\"))))) (t (forward-char -1) (if (looking-at "\\\\") (progn (skip-chars-backward " \t") (kill-line)))))) ;;; This page covers commenting out multiple lines. (defun c++-comment-region () "Comment out all lines in a region between mark and current point by inserting \"// \" (comment-start)in front of each line." (interactive) (let* ((m (if (eq (mark) nil) (error "Mark is not set!") (mark))) (start (if (< (point) m) (point) m)) (end (if (> (point) m) (point) m)) (mymark (copy-marker end))) (save-excursion (goto-char start) (while (< (point) (marker-position mymark)) (beginning-of-line) (insert comment-start) (beginning-of-line) (next-line 1) )))) (defun c++-uncomment-region () "Uncomment all lines in region between mark and current point by deleting the leading \"// \" from each line, if any." (interactive) (let* ((m (if (eq (mark) nil) (error "Mark is not set!") (mark))) (start (if (< (point) m) (point) m)) (end (if (> (point) m) (point) m)) (mymark (copy-marker end)) (len (length comment-start)) (char (string-to-char comment-start)) ) (save-excursion (goto-char start) (while (< (point) (marker-position mymark)) (beginning-of-line) (if (looking-at (concat " *" comment-start)) (progn (zap-to-char 1 char) (delete-char len))) (beginning-of-line) (next-line 1) )))) ;;; Below are two regular expressions that attempt to match defuns ;;; "strongly" and "weakly." The strong one almost reconstructs the ;;; grammar of C++; the weak one just figures anything id or curly on ;;; the left begins a defun. The constant "c++-match-header-strongly" ;;; determines which to use; the default is the weak one. (defvar c++-match-header-strongly nil "*If NIL, use c++-defun-header-weak to identify beginning of definitions,\ if nonNIL, use c++-defun-header-strong") (defvar c++-defun-header-strong-struct-equivs "\\(class\\|struct\\|enum\\)" "Regexp to match names of structure declaration blocks in C++") (defconst c++-defun-header-strong (let* (; valid identifiers ;; There's a real wierdness here -- if I switch the below (id "\\(\\w\\|_\\)+") ;; to be ;; (id "\\(_\\|\\w\\)+") ;; things no longer work right. Try it and see! ; overloadable operators (op-sym1 "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?") (op-sym2 "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]") (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)")) ; whitespace (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*") (c-comment (concat "/\\*" middle "\\*+/")) (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)")) (wh-opt (concat wh "*")) (wh-nec (concat wh "+")) (oper (concat "\\(" "operator" "\\(" wh-opt op-sym "\\|" wh-nec id "\\)" "\\)")) (dcl-list "([^():]*)") (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)")) (inits (concat "\\(:" "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*" wh-opt id "(.*)" wh-opt "{" "\\|" wh-opt "{\\)")) (type-name (concat "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?" id)) (type (concat "\\(const" wh-nec "\\)?" "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|" type-name wh-opt "&" "\\)")) (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)") (modifiers (concat "\\(" modifier wh-nec "\\)*")) (func-header ;; type arg-dcl (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits)) (inherit (concat "\\(:" wh-opt "\\(public\\|private\\)?" wh-nec id "\\)")) (cs-header (concat c++-defun-header-strong-struct-equivs wh-nec id wh-opt inherit "?" wh-opt "{")) ) (concat "^\\(" func-header "\\|" cs-header "\\)")) "Strongly-defined regexp to match beginning of structure \ or function definition. ") ;; This part has to do with recognizing defuns. ;; The weak convention we will use is that a defun begins any time ;; there is a left curly brace, or some identifier on the left margin, ;; followed by a left curly somewhere on the line. (This will also ;; incorrectly match some continued strings, but this is after all ;; just a weak heuristic.) Suggestions for improvement (short of the ;; strong scheme shown above) are welcomed. (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{" "Weakly-defined regexp to match beginning of structure \ or function definition. ") (defun c++-beginning-of-defun (arg) (interactive "p") (let ((c++-defun-header (if c++-match-header-strongly c++-defun-header-strong c++-defun-header-weak))) (cond ((or (= arg 0) (and (> arg 0) (bobp))) nil) ((and (not (looking-at c++-defun-header)) (let ((curr-pos (point)) (open-pos (if (search-forward "{" nil 'move) (point))) (beg-pos (if (re-search-backward c++-defun-header nil 'move) (match-beginning 0)))) (if (and open-pos beg-pos (< beg-pos curr-pos) (> open-pos curr-pos)) (progn (goto-char beg-pos) (if (= arg 1) t nil));; Are we done? (goto-char curr-pos) nil)))) (t (if (and (looking-at c++-defun-header) (not (bobp))) (forward-char (if (< arg 0) 1 -1))) (and (re-search-backward c++-defun-header nil 'move (or arg 1)) (goto-char (match-beginning 0))))))) (defun c++-end-of-defun (arg) (interactive "p") (let ((c++-defun-header (if c++-match-header-strongly c++-defun-header-strong c++-defun-header-weak))) (if (and (eobp) (> arg 0)) nil (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1)) (let ((pos (point))) (c++-beginning-of-defun (if (< arg 0) (- (- arg (if (eobp) 0 1))) arg)) (if (and (< arg 0) (bobp)) t (if (re-search-forward c++-defun-header nil 'move) (progn (forward-char -1) (forward-sexp) (beginning-of-line 2))) (if (and (= pos (point)) (re-search-forward c++-defun-header nil 'move)) (c++-end-of-defun 1)))) t )) ) (defun c++-indent-defun () "Indents the current function def, struct or class decl." (interactive) (let ((restore (point))) (c++-end-of-defun 1) (beginning-of-line 1) (let ((end (point))) (c++-beginning-of-defun 1) (while (<= (point) end) (c++-indent-line) (next-line 1) (beginning-of-line 1))) (goto-char restore))) beginning-of-line 2))) (if (and (= pos (point)) (re-search-forward c++-defun-header nil 'move)) (c++-end-of-defun 1)))) t )) ) (defun c++-indent-defun () "Indents the current function def, struct or class decl." (interactive) (let ((restore (poilibg++/etc/trie-gen/trie-gen.1 600 473 0 7027 4677700004 11211 .TH TRIE-GEN 1 "12 December 1989" "Version 1.0" .de BP .sp .ti -.2i \(** .. .SH NAME trie-gen \- generate a minimal-prefix trie .SH SYNOPSIS .B trie-gen [ .B \-c ] < keyfile .SH DESCRIPTION .I TRIE-GEN is a program that reads a user-specified set of keywords from standard input and generates a minimal-prefix trie. Minimal-prefix tries have several useful properties that make them efficient implementations for static search sets. The table-driven trie generated by TRIE-GEN recognizes keywords in the search set in time proportional to the length of the shortest unambiguous prefix for a given keyword. Consider a command interpreter for an interactive debugger or operating system shell (e.g., gdb or VMS). It is frequently nice to allow users to type the `minimal unambiguous prefix' for any command in the set of built-in keywords. For example, given the following complete list of system commands: .nf ---------------------------------------- bash bison diff diff3 egrep flex g++ gawk gcc gdb genclass gnuchess gnuplot gperf grep indent make sed ---------------------------------------- .fi and assuming these are the only available commands, a user could invoke the egrep program simply by entering a single `e', but would need to enter `ba' to run bash or `gnuc' to run gnuchess. .I TRIE-GEN generates several static lookup tables and two functions that allow client programs to either interpret standard input one character at a time or, given a prefix string, to determine which keyword in the static search set this prefix string matches. The trie generation algorithm runs in time proportional to O(n * k), where .I n is the number of user-specified keywords from the standard input and .I k is the length of the longest common prefix between any words in the keyword set. The table compaction algorithm, invoked by giving the `-c' option, runs in time proportional to O(r * e * 128), where .I r is the total number of rows in the generated trie, .I e is the maximum number of non-null entries in each row, and 128 is the size of the ASCII character set used to index into the trie. .SH OPTIONS .TP .B \-c Compact the generated trie using a technique called `double-offset indexing,' which is used in Bison and FLEX (also described in Tarjan and Yao's article ``Storing a Sparse Table'' in CACM, 1979). .B \-f Generates a `full' trie rather than a minimal-prefix trie. .SH "SEE ALSO" gperf (the GNU perfect hash function generator) .SH BUGS None known at this time, though there is much work to be done with the user interface and program options... Bugs should be reported to .BR schmidt@ics.uci.edu . Bugs tend actually to be fixed if they can be isolated, so it is in your interest to report them in such a way that they can be easily reproduced. .SH COPYING Copyright (c) 1989 Free Software Foundation, Inc. .P 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. .P 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. .P 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 included in translations approved by the Free Software Foundation instead of in the original English. .SH AUTHORS Douglas C. Schmidt (schmidt@ics.uci.edu) der 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. .P 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 included in translations approved by the Free Software Foundation instead of in the original English. .SH AUTHORS Douglas C. Schmidtlibg++/etc/trie-gen/Makefile 600 473 0 7104 4677700004 11051 # Copyright (C) 1989 Free Software Foundation, Inc. # written by Douglas C. Schmidt (schmidt@ics.uci.edu) # # This file is part of GNU TRIE-GEN. # # GNU TRIE-GEN 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 1, or (at your option) # any later version. # # GNU trie-gen 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 GNU trie-gen; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # ------ source locations # source directory for libg++.a SRCDIR = ../../src # source include directory SRCIDIR= ../../g++-include # ------ installation destinations prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ $(OSLDFLAG) # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< OBJS = trie.o compact.o main.o version.o options.o all: trie-gen trie-gen: $(OBJS) $(GXX) $(GXXFLAGS) -o trie-gen $(OBJS) $(GXXLDFLAGS) test: trie-gen @echo "Generating a compacted minimal-prefix trie for files in /bin" /bin/ls -1 /bin | ./trie-gen -c > out.c $(GXX) $(DFLAGS) out.c test.c /bin/ls -1 /bin | ./a.out -v distrib: (cd ..; rm -f trie-gen.tar.Z; tar cvf trie-gen.tar trie-gen; compress trie-gen.tar) clean: -rm -f trie-gen *.o a.out out.c core *~ #*# mon.out # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. compact.o : compact.cc compact.h main.o : main.cc options.h trie.h compact.h options.o : options.cc options.h trie.o : trie.cc trie.h compact.h version.o : version.cc # IF YOU PUT ANYTHING HERE IT WILL GO AWAY st.c /bin/ls -1 /bin | ./a.out -v distrib: (cd ..; rm -f trie-gen.tar.Z; tar cvf trie-gen.tar trie-gen; compress trie-gen.tar) clean: -rm -f trie-gen *.o a.out out.c core *~ #*# mon.out # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. compact.o : compact.cc compact.h main.o : main.cc options.h trie.h compact.h options.o : options.cc options.h trie.o : trie.cc trie.h compact.h libg++/etc/trie-gen/main.cc 600 473 0 3013 4677700004 10637 /* Driver routine for the minimal-prefix trie generator. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU trie-gen; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "options.h" #include "trie.h" int main (int argc, char **argv) { option (argc, argv); #ifdef UNLIMIT_STACK /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } #endif /* UNLIMIT_STACK */ File input (stdin); Trie Trie (Trie::DEFAULT_SIZE); char *buf; for (int i = 0; input.gets (&buf); i++) Trie.insert (buf, input.iocount ()); Trie.output (); } option (argc, argv); #ifdef UNLIMIT_STACK /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } #endif /* UNLIMIT_STACK */ File input (stdin); Trie Trie (Trie::DEFAULT_SIZE); char *buf; for (int i = 0; input.gets (&buf); i++) Trie.insert (buf, input.iocount ()); Trie.oulibg++/etc/trie-gen/options.cc 600 473 0 15153 4677700004 11436 /* Handles parsing the Options provided to the user. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU TRIE-GEN; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "options.h" /* Global option coordinator for the entire program. */ Options option; /* Current program version. */ extern char *version_string; static void report_error (const char *format, ...) { va_list args; va_start (args, format); char c; while (c = *format++) { if (c=='%') switch (c = *format++) { case 'a': exit (1); case 'n': fputs (option.program_name (), stderr); break; case 'e': typedef void (*CallbackT) (void); CallbackT callback = va_arg (args, CallbackT); (*callback) (); break; case 's': fputs (va_arg (args, const char *), stderr); break; default: fputc (c, stderr); } else fputc (c, stderr); } va_end (args); } /* Prints program usage to standard error stream. */ static inline void Options::usage (void) { report_error ("Usage: %n [-cdf] (type %n -h for help)\n"); } /* Output command-line Options. */ void Options::print_options (void) { int i; printf ("/* Command-line: "); for (i = 0; i < argument_count; i++) printf ("%s ", argument_vector[i]); printf (" */"); } /* Sets the default Options. */ Options::Options (void) { option_word = 0; } /* Dumps option status when debug is set. */ Options::~Options (void) { if (option_word & DEBUG) { fprintf (stderr, "\ndumping Options:\nCOMPACT is.......: %s\nDEBUG is.......: %s" "\nFULL is........: %s\nCONST is.......: %s", option_word & COMPACT ? "enabled" : "disabled", option_word & DEBUG ? "enabled" : "disabled", option_word & FULL ? "enabled" : "disabled", option_word & CONST ? "enabled" : "disabled"); fprintf (stderr, "\nfinished dumping Options\n"); } } /* Parses the command line Options and sets appropriate flags in option_word. */ void Options::operator () (int argc, char *argv[]) { GetOpt getopt (argc, argv, "cCdfh"); int option_char; argument_count = argc; argument_vector = argv; while ((option_char = getopt ()) != EOF) { switch (option_char) { case 'c': /* Compact the output tables. */ { option_word |= COMPACT; break; } case 'C': /* Make the generated tables readonly (const). */ { option_word |= CONST; break; } case 'd': /* Enable debugging option. */ { option_word |= DEBUG; report_error ("Starting program %n, version %s, with debuggin on.\n", version_string); break; } case 'f': /* Generate a full table */ { option_word |= FULL; break; } case 'h': { report_error ("-c\tCompact the generated trie.\n" "-C\tMake strings in the generated lookup table constant, i.e., readonly.\n" "-d\tEnable debugging (produces verbose output to standard error).\n" "-f\tGenerates a `full' trie rather than a minimal-prefix trie.\n" "-h\tPrints out the help diagnostic.\n%a"); } default: report_error ("%e%a", usage); } } if (argv[getopt.optind] && ! freopen (argv[getopt.optind], "r", stdin)) report_error ("Unable to read key word file %s.\n%e%a", argv[getopt.optind], usage); if (++getopt.optind < argc) report_error ("Extra trailing arguments to %n.\n%e%a", usage); } #ifndef __OPTIMIZE__ const char * Options::program_name (void) { return argument_vector[0]; } /* TRUE if option enable, else FALSE. */ int Options::operator[] (Option_Type option) { return option_word & option; } /* Enables option OPT. */ void Options::operator= (enum Option_Type opt) { option_word |= opt; } /* Disables option OPT. */ void Options::operator!= (enum Option_Type opt) { option_word &= ~opt; } /* Initializes the key Iterator. */ void Options::reset (void) { key_pos = 0; } /* Returns current key_position and advances index. */ int Options::get (void) { return key_positions[key_pos++]; } /* Sets the size of the table size. */ void Options::set_asso_max (int r) { size = r; } /* Returns the size of the table size. */ int Options::get_asso_max (void) { return size; } /* Returns total distinct key positions. */ int Options::get_charset_size (void) { return total_charset_size; } /* Sets total distinct key positions. */ void Options::set_charset_size (int size) { total_charset_size = size; } /* Returns the jump value. */ int Options::get_jump (void) { return jump; } /* Returns the lookup function name. */ const char * Options::get_function_name (void) { return function_name; } /* Returns the keyword key name. */ const char * Options::get_key_name (void) { return key_name; } /* Returns the hash function name. */ const char * Options::get_hash_name (void) { return hash_name; } /* Returns the initial associated character value. */ int Options::initial_value (void) { return initial_asso_value; } /* Returns the iterations value. */ int Options::get_iterations (void) { return iterations; } /* Returns the string used to delimit keywords from other attributes. */ const char * Options::get_delimiter () { return delimiters; } /* Gets the total number of switch statements to generate. */ int Options::get_total_switches () { return total_switches; } #endif /* not defined __OPTIMIZE__ */ ial associated character value. */ int Options::initial_value (void) { return initial_asso_value; } /* Returns the iterations value. */ int Options::get_iterations (void) { return iterations; } /* Returns the string used to delimit keywords from other attributes. */ const char * Options::get_delimiter () { return delimiters; } /* Gets the total number of switch statements to generate. */libg++/etc/trie-gen/options.h 600 473 0 5471 4677700005 11263 /* This may look like C code, but it is really -*- C++ -*- */ /* Handles parsing the Options provided to the user. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU TRIE-GEN; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This module provides a uniform interface to the various options available to a user of the minimal-prefix trie generator. The overall design of this module was an experiment in using C++ classes as a mechanism to enhance centralization of option and and error handling, which tend to get out of hand in a C program. */ #pragma once /* Enumerate the potential debugging Options. */ enum Option_Type { DEBUG = 01, /* Enable debugging option. */ COMPACT = 02, /* Compact the output tables. */ FULL = 04, /* Generate a full table. */ CONST = 010, /* Make the generated tables readonly (const). */ }; /* Class manager for program options. */ class Options { public: Options (void); ~Options (void); const char *program_name (void); int operator[] (Option_Type option); void operator() (int argc, char *argv[]); void operator= (enum Option_Type); void operator!= (enum Option_Type); static void print_options (void); private: static int option_word; /* Holds the user-specified Options. */ static int argument_count; static char **argument_vector; static void usage (void); /* Prints proper program usage. */ }; /* Global option coordinator for the entire program. */ extern Options option; #ifdef __OPTIMIZE__ inline const char * Options::program_name (void) { return argument_vector[0]; } inline int Options::operator[] (Option_Type option) /* True if option enable, else false. */ { return option_word & option; } inline void Options::operator = (enum Option_Type opt) /* Enables option OPT. */ { option_word |= opt; } inline void Options::operator != (enum Option_Type opt) /* Disables option OPT. */ { option_word &= ~opt; } #endif ram. */ extern Options option; #ifdef __OPTIMIZE__ inline const char * Options::program_name (void) { return argument_vector[0]; } inline int Options::operator[] (Option_Type option) /* libg++/etc/trie-gen/test.c 600 473 0 1106 4677700005 10531 /* Tests the generated perfect has function. The -v option prints diagnostics as to whether a word is in the set or not. Without -v the program is useful for timing. */ #include #define MAX_LEN 200 char *in_word_set (const char *, int); int main (int argc, char *argv[]) { int verbose = argc > 1 ? 1 : 0; char buf[MAX_LEN]; char *s; while (gets (buf)) if ((s = in_word_set (buf, strlen (buf))) && verbose) printf ("%s is prefix for %s\n", buf, s); else if (verbose) printf ("NOT in word set %s\n", buf); return 0; } s diagnostics as to whether a word is in the set or not. Without -v the program is useful for timing. */ #include #define MAX_LEN 200 char *in_word_set (const char *, int); int main (int argc, char *argv[]) { int verbose = argc > 1 ? 1 : 0; char buf[MAX_LEN]; char *s; while (gets (buf)) if ((s = in_word_set (buf, strlen (buf))) && verbose) printf ("%s is prefix for %s\n", buf, s); else if libg++/etc/trie-gen/trie.h 600 473 0 4143 4677700005 10526 /* This may look like C code, but it is really -*- C++ -*- */ /* Data and member functions for generating a minimal-prefix trie. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU trie-gen; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "compact.h" class Trie { public: Trie (int n): matrix (n), total_size (n) { keys = new char *[n]; } void insert (char *str, int len); void output (void); void sort (void); const int DEFAULT_SIZE = 1000; /* Starting guess on the total number of keys. */ private: const int MAX_SIGNED_CHAR = 127; const int MAX_SIGNED_SHORT = 32767; const int MAX_ASCII = 128; Compact_Matrix matrix; /* Dynamic table encoding the trie DFA. */ char **keys; /* Dynamic resizable table to store input keys. */ int column = 0; /* Tracks the current column during trie generation. */ int total_size; /* Total size of the keyword table. */ int current_size; /* Current size of the keyword table. */ int max_row = 1; /* Largest row in the trie so far. */ int max_key_len = 0; /* Length of the longest keyword. */ void resize (int new_size); void build (int hi, int lo = 0, int col = 0); static int cmp (char **s1, char **s2); }; n = 0; /* Tracks the current column during trie generation. */ int total_size; /* Total size of the keyword table. */ int current_size; /* Current size of the keyword table. */ int max_row = 1; /* Largest row in the trie so far. */ int max_key_len = 0; /* Length of the longest keyword. */ void resize (int new_size); void libg++/etc/trie-gen/trie.cc 600 473 0 14252 4677700005 10706 /* Generates a minimal-prefix trie for a user-specified set of keywords. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU trie-gen; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "options.h" #include "trie.h" /* Insert a new keyword into the data structure, possibly growing the keyword table to accomodate the new entry. Space for STR has already been allocated in the caller. In addition, the MAX_KEY_LEN is updated if the current LEN is larger than the previous max. This information is needed later on when dynamically allocating the TRIE table. */ void Trie::insert (char *str, int len) { if (current_size >= total_size) resize (total_size * 2); keys[current_size++] = str; max_key_len >?= len; } /* Grow the KEYS table to allow a maximum of NEW_SIZE entries. Old keys are copied into the new buffer. */ void Trie::resize (int new_size) { keys = new {keys, total_size = new_size} char *; } /* Write the generated TRIE out as a static table. Compaction is performed if the user requests it, otherwise the table is not compacted at all! (this leads to ridiculously large tables; perhaps compaction should be the default?) */ void Trie::output (void) { if (current_size <= 0) return; else { sort (); fputs ("#define MAX_ASCII 128\n\nstatic", stdout); if (option[CONST]) fputs (" const", stdout); fputs (" char *const word_list[] = \n{\n \"\",\n", stdout); for (int i = 0; i < current_size; i++) printf (" \"%s\",\n", keys[i]); fflush (stdout); fputs ("};\n\n", stdout); build (current_size); if (option[COMPACT]) matrix.output (); else { const int MAX_NUMBER = current_size >? max_row; int field_width; int count = MAX_NUMBER; for (field_width = 2; (count /= 10) > 0; field_width++) ; printf ("static const %s trie_array[][MAX_ASCII] = \n{", MAX_NUMBER < MAX_SIGNED_CHAR ? "char" : MAX_NUMBER < MAX_SIGNED_SHORT ? "short" : "int"); for (i = 0; i < max_row; i++) { fputs ("\n ", stdout); for (int j = 0; j < MAX_ASCII; j++) printf ("%*d,", field_width, matrix (i, j)); } fputs ("\n};\n", stdout); } printf ("\n%schar *\nin_word_set (const char *str, int len)\n{\n" " %schar *s = str;\n int i = 0;\n\n" " while ((i = %s) > 0)\n ;\n\n" " return i == 0 || strncmp (s = word_list[-i], str, len)" " ? 0 : s;\n}\n", option[CONST] ? "const " : "", option[CONST] ? "const " : "", option[COMPACT] ? "next_state(i, *s++)" : "trie_array[i][*s++]"); } } /* Comparison routine called by qsort. */ int Trie::cmp (char **s1, char **s2) { return strcmp (*s1, *s2); } /* Sort the keys by lexicographical order. */ void Trie::sort (void) { typedef int (*PTF)(void *, void *); qsort ((void *) keys, current_size, sizeof *keys, PTF (cmp)); } /* Generate the trie, using recursive calls if necessary to handle duplicate keyword index positions. */ void Trie::build (int hi, int lo, int col) { if (option[FULL]) { int row = max_row - 1; /* Process each key in the range lo..hi, possibly calling the function recursively when duplicate consecutive characters are found (that's why it is important to sort the keywords first!). Note that calls to member function MATRIX build the internal form used to generate the compacted sparse array. Positive values indicate the next row (which really encodes DFA states) to consider; negative values are flags that provide (when negated) the correct offset into a generated array of strings. */ for (int i = lo; i < hi; i++) if (keys[i][col] == '\0') matrix (row, keys[i][col], -i - 1); else { /* Location the end of the duplicate characters in the current column. */ for (lo = i; i < hi - 1 && keys[i][col] == keys[i + 1][col]; i++) ; matrix (row, keys[lo][col], max_row++); build (i + 1, lo, col + 1); } } else { int row = max_row - 1; /* Process each key in the range lo..hi, possibly calling the function recursively when duplicate consecutive characters are found (that's why it is important to sort the keywords first!). Note that calls to member function MATRIX build the internal form used to generate the compacted sparse array. Positive values indicate the next row (which really encodes DFA states) to consider; negative values are flags that provide (when negated) the correct offset into a generated array of strings. */ for (int i = lo; i < hi; i++) if (keys[i][col] == '\0' || i == hi - 1 || keys[i][col] != keys[i + 1][col]) matrix (row, keys[i][col], -i - 1); else { /* Location the end of the duplicate characters in the current column. */ for (lo = i; i < hi - 1 && keys[i][col] == keys[i + 1][col]; i++) ; matrix (row, keys[lo][col], max_row++); build (i + 1, lo, col + 1); } } } for (int i = lo; i < hi; i++) if (keys[i][col] == '\0' || i == hi - 1 || keys[i][col] != keys[i + 1][col]) matrix (row, keys[i][col], -i - 1); else { /* Location the end of the duplicate characters in the current column. */ for (lo = i; i < hi - 1 && keys[i][col] libg++/etc/trie-gen/compact.h 600 473 0 7017 4677700005 11214 /* This may look like C code, but it is really -*- C++ -*- */ /* Compact a sparse 2-D matrix. Uses the Tarjan and Yao algorithm taken from the article ``Storing a Sparse Table'' in CACM, 1979. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU trie-gen; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This really should go in the class scope, but alas g++ doesn't like that... */ typedef int ITEM_TYPE; class Compact_Matrix { public: Compact_Matrix (ITEM_TYPE *mat, int rows, int cols); Compact_Matrix (int default_rows = 0); ITEM_TYPE operator () (int i, int j); void operator () (int i, int j, ITEM_TYPE value); void output (void); private: struct Column_Node { int index; /* Actual column index in the current row. */ ITEM_TYPE value; /* Value at this index location. */ Column_Node *next; /* Pointer to next column in the row. */ Column_Node (Column_Node *p, int i, ITEM_TYPE v): index (i), value (v), next (p) {} }; struct Row_Node { Column_Node *col_list = 0; /* List of column index values for this row. */ int count = 0; /* Count of total number of columns in the list. */ }; const int MAX_INT = ~unsigned (0) >> 1; const int MAX_SIGNED_CHAR = 127; const int MAX_ASCII_RANGE = 128; const int MAX_SIGNED_SHORT = 32767; const int MAX_UNSIGNED_CHAR = 255; const int MAX_UNSIGNED_SHORT = 65535; int max_col_count = 0; /* Total number of columns in largest row. */ int total_cols = 0; /* Total number of columns in the matrix (if applicable). */ int total_entries = 0; /* Total number of non-null entries in the matrix. */ int compressed_len = -1; /* Size of the compacted matrix buffer. */ int *row_offsets = 0; /* Dynamic buffer used for double-offset indexing. */ int *checks = 0; /* Dynamic buffer used for double-offset indexing. */ int current_rows = 0; /* Current items in ROW_VEC, at this point. */ int max_rows = 0; /* Maximum size of ROW_VEC, at this point. */ Row_Node *row_vec = 0; /* Dynamic buffer indexed by row number. */ Column_Node **bucket_vec = 0; /* Dynamic buffer used to sort by column count. */ ITEM_TYPE *values = 0; /* Dynamic buffer containing non-null matrix values. */ ITEM_TYPE *matrix = 0; /* Pointer to 2-D matrix (if appropriate). */ void resize (int new_size); void first_fit_decreasing (void); void bucket_sort (void); void output_lookup (void); void output_arrays (void); void dump_entries (void); void dump_bucket (void); }; = 0; /* Dynamic buffer used to sort by column count. */ ITEM_TYPE *values = 0; /* Dynamic buffer containing non-null matrix values. */ ITEM_TYPE *matrix = 0; /* Pointer to 2-D matrix (if appropriate). */ void resize (int new_size); void first_fit_decreasing (void); void bucket_sort (void); void output_lookup (void); void output_arrays (void); void dump_entries (void); void dump_buclibg++/etc/trie-gen/compact.cc 600 473 0 26741 4677700006 11400 /* Compact a sparse 2-D matrix. Uses the Tarjan and Yao algorithm taken from the article ``Storing a Sparse Table'' in CACM, 1979. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU trie-gen; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "compact.h" /* Essentially provides the functionality of `calloc.' */ static inline void * operator new (size_t elem_size, int size) { void *temp = new char[elem_size * size]; bzero (temp, elem_size * size); return temp; } /* Essentially combines the functionality of `realloc' and `calloc'. */ static inline void * operator new (size_t elem_size, void *old_ptr, int old_size, int new_size) { old_ptr = new {old_ptr, new_size * elem_size} char; bzero (old_ptr + old_size * elem_size, (new_size - old_size) * elem_size); return old_ptr; } /* Initializes the internal form in the case that the user passes in a pointer to an already existing 2-dimensional matrix. Note that by declaring the matrix to be a 1-dimensional array we can perform the col and row offset calculations ourselves and handle matrices with fixed, but arbitrary-sized columns and rows. */ Compact_Matrix::Compact_Matrix (ITEM_TYPE *mat, int rows, int cols): matrix (mat), max_rows (rows), total_cols (cols), current_rows (rows) { row_vec = new Row_Node[rows]; for (int i = 0; i < max_rows; i++) for (int j = 0; j < total_cols; j++) if (matrix[i * total_cols + j] != 0) { ITEM_TYPE value = matrix[i * total_cols + j]; total_entries++; row_vec[i].count++; row_vec[i].col_list = new Column_Node (row_vec[i].col_list, j, value); } } /* Initializer for the case where we don't have a previously created matrix to play with. DEFAULT_ROWS represents the best first approximation as to the number of rows in the matrix. However, this buffer is resized as needed, so the algorithm isn't overly penalized for a bad first guess. */ Compact_Matrix::Compact_Matrix (int default_rows): max_rows (default_rows) { row_vec = default_rows ? new Row_Node[default_rows] : 0; } /* Returns the `matrix[i][j]' item in the sparse 2-dimensional matrix. Note that if the matrix is very sparse the number of items in each COL_LIST will be very short, hence linear search is not too inefficent. */ ITEM_TYPE Compact_Matrix::operator () (int i, int j) { assert (i >= 0 && i < current_rows && j >= 0); for (Column_Node *col_list = row_vec[i].col_list; col_list; col_list = col_list->next) if (col_list->index == j) return col_list->value; return 0; } /* Sets `matrix[i][j]' to VALUE. ROW_VEC is dynamically resized, if necessary. At the moment the new entry is simply pushed onto the linked list of COL_LIST entries. If there aren't many elements then this will not be too inefficient for later retrieval. */ void Compact_Matrix::operator () (int i, int j, ITEM_TYPE value) { if (i >= max_rows) resize (max_rows * 2); row_vec[i].col_list = new Column_Node (row_vec[i].col_list, j, value); total_entries++; row_vec[i].count++; current_rows >?= i + 1; } /* Enlarges the ROW_VEC from CURR_ROWS to NEW_SIZE. */ void Compact_Matrix::resize (int new_size) { Row_Node *temp = new Row_Node[max_rows = new_size]; bcopy ((void *) row_vec, (void *) temp, current_rows * sizeof *row_vec); delete row_vec; row_vec = temp; } /* Calls the functions that compact the table and generate the resulting lookup scheme. */ void Compact_Matrix::output (void) { bucket_sort (); first_fit_decreasing (); output_arrays (); output_lookup (); } /* Performs a bucket sort so that all rows with the same number of non-null entries are treated as part of the same equivalence class. This operation is very fast! */ void Compact_Matrix::bucket_sort (void) { for (int i = 0; i < current_rows; i++) max_col_count >?= row_vec[i].count; bucket_vec = new {max_col_count + 1} Column_Node *; for (i = 0; i < current_rows; i++) bucket_vec[row_vec[i].count] = new Column_Node (bucket_vec[row_vec[i].count], i, 0); } /* Useful macros to clarify subsequent code. They should probably be made into member functions... */ #define STARTING_ROW_OFFSET(X) (row_offsets[(X)]) #define LARGEST_COL_VALUE(X) (row_vec[(X)].col_list->index) #define COL_LIST(X) (row_vec[(X)].col_list) #define COL_COUNT(X) (row_vec[(X)].count) #define COL_INDEX(X) ((X)->index) #define ROW_INDEX(X) ((X)->index) /* Performs sparse 2-dimensional array compaction suitable for use with the `double-offset indexing' (used by Bison and FLEX to compact the size of the sparse LR parsing tables and DFA's). This function implements the `first fit decreasing' heuristic described in Tarjan and Yao's paper ``Storing a Sparse Table'' in CACM, 1979. */ void Compact_Matrix::first_fit_decreasing (void) { /* Bit-vector and counter that records if a row/col location is already set. */ int current_max = current_rows + (total_cols >? MAX_ASCII_RANGE); char *already_assigned = (char *) alloca (current_max); bzero (already_assigned, current_max); row_offsets = new {current_rows} int; values = new {current_max} ITEM_TYPE; checks = new {current_max} int; for (int row_index = max_col_count; row_index >= 0; row_index--) if (bucket_vec[row_index]) /* Process every row in the `equivalence class' of rows containing the same number of non-null column entries. */ for (Column_Node *rows_list = bucket_vec[row_index]; rows_list; rows_list = rows_list->next) { int row = ROW_INDEX (rows_list); int row_offset = STARTING_ROW_OFFSET (row); /* Process every column index in the current row. */ for (Column_Node *col_list = COL_LIST (row); ;) { int col = COL_INDEX (col_list); /* If we exceed the boundaries it's time to resize various buffers. */ if (row_offset + col >= current_max) { int new_size = (current_max >? row_offset + col) * 2; char *temp = (char *) alloca (new_size); bcopy (already_assigned, temp, current_max); bzero (temp + current_max, new_size - current_max); already_assigned = temp; values = new {values, current_max, new_size} int; checks = new {checks, current_max, new_size} int; current_max *= 2; } if (already_assigned[row_offset + col]) { /* Efficiency hack to skip over obvious collisions. */ while (++row_offset + col < current_max && already_assigned[row_offset + col]) ; /* Reset col_list and begin again (with new row offset). */ col_list = COL_LIST (row); } else if ((col_list = col_list->next) == 0) break; } /* No more collisions exist. Record the positions for the next round. */ for (col_list = COL_LIST (row); col_list; col_list = col_list->next) { int offset = row_offset + COL_INDEX (col_list); already_assigned[offset] = 1; compressed_len >?= offset; values[offset] = col_list->value; checks[offset] = row; } /* Need to reset this once all is said and done! */ STARTING_ROW_OFFSET (row) = row_offset; } } /* Generates the three arrays that comprise the `double-offset index' scheme. This is a bit messy, since I'm trying to neatly format the generated tables and also determine the smallest (in bytes) type declarations necessary to represent the elements of the tables. */ void Compact_Matrix::output_arrays () { const int COL_WIDTH = 12; int max_number = 0; int count; printf ("#ifndef __STDC__\n#define const\n#endif\n\n"); printf ("#define YY_LAST %d\n", compressed_len); for (int i = 0; i < current_rows; i++) max_number >?= row_offsets[i]; count = max_number; for (int field_width = 1; (count /= 10) > 0; field_width++) ; printf ("\nstatic const unsigned %s yy_rows[%d] = \n{\n ", max_number < MAX_UNSIGNED_CHAR ? "char" : max_number < MAX_UNSIGNED_SHORT ? "short" : "int", current_rows); for (i = 0; i < current_rows; ) printf ("%*d,%s", field_width, row_offsets[i], ++i % COL_WIDTH ? " " : "\n "); max_number = 0; for (i = 0; i < compressed_len + 1; i++) max_number >?= checks[i]; count = max_number; for (field_width = 1; (count /= 10) > 0; field_width++) ; printf ("\n};\n\nstatic const unsigned %s yy_check[%d] = \n{\n ", max_number < MAX_UNSIGNED_CHAR ? "char" : max_number < MAX_UNSIGNED_SHORT ? "short" : "int", compressed_len + 1); for (i = 0; i < compressed_len + 1; ) printf ("%*d,%s", field_width, checks[i], ++i % COL_WIDTH ? " " : "\n "); max_number = 0; for (i = 0; i < compressed_len + 1; i++) max_number >?= abs (values[i]); count = max_number; for (field_width = 2; (count /= 10) > 0; field_width++) ; printf ("\n};\n\nstatic const %s yy_next[%d] = \n{\n ", max_number < MAX_SIGNED_CHAR ? "char" : max_number < MAX_SIGNED_SHORT ? "short" : "int", compressed_len + 1); for (i = 0; i <= compressed_len; ) printf ("%*d,%s", field_width, values[i], ++i % COL_WIDTH ? " " : "\n "); printf ("\n};\n\n"); } /* Generates the `double-offset index' function, that provides the value stored in the location referenced by parameters ROW and COL. */ void Compact_Matrix::output_lookup (void) { printf ("static inline int\nnext_state " "(int row, int col)\n{\n int state_index = yy_rows[row] + col;\n\n" " if (state_index > YY_LAST || yy_check[state_index] != row)\n " "return 0;\n else\n return yy_next[state_index];\n}\n"); } /* Useful debugging routine. */ void Compact_Matrix::dump_entries (void) { for (int i = 0; i < current_rows; i++) if (row_vec[i].col_list) { Column_Node *temp = row_vec[i].col_list; fprintf (stderr, "row %d's count = %d, cols = ", i, row_vec[i].count); do { fprintf (stderr, "%d ", temp->index); } while (temp = temp->next); putc ('\n', stderr); } } /* Useful debugging routine. */ void Compact_Matrix::dump_bucket (void) { for (int i = 0; i < total_entries; i++) if (bucket_vec[i]) { Column_Node *temp = bucket_vec[i]; fprintf (stderr, "bucket %d = ", i); do { fprintf (stderr, "%d ", temp->index); } while (temp = temp->next); putc ('\n', stderr); } } i, row_vec[i].count); libg++/etc/trie-gen/ChangeLog 600 473 0 2151 4677700006 11162 Fri Feb 23 19:44:10 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Added the `-h' option to print out a verbose help message. * Added a check in Trie::output that ensures the program doesn't crash if no keywords are given! * Implemented the -f (generate full trie) option. This is useful to generate another example program for my USENIX C++ paper! * Removed the member field `compact_output' from class Trie. Changed all uses of this variable to option[COMPACT]. Why was it ever done the other way anyhow?! * Added the `-C' CONST option so that user's can declare strings in the generated lookup table to be readonly. Fri Feb 16 10:47:02 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Killed some debugging code in compact.cc (operator new). Thu Feb 15 23:20:44 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed a bunch of incredibly stupid errors. (I can't believe this thing even worked before...). That's what happens when you don't hack for 2 months ;-( ed the `-C' CONST option so that user's can declare strings in the generated lookup table to be readonly. Fri Feb 16 10:47:02 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Killed some debugging code in compact.cc (operator new). Thu Feb 15 23:20:44 1990 Doug Schmidt (schmidt at zola.ics.uci.edu) * Fixed a bunch of incredibly stupid errors. (I can't believe libg++/etc/trie-gen/version.cc 600 473 0 1556 4677700006 11414 /* Current program version number. Copyright (C) 1989 Free Software Foundation, Inc. written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU TRIE-GEN. GNU TRIE-GEN 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 1, or (at your option) any later version. GNU TRIE-GEN 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 GNU TRIE-GEN; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ char *version_string = "1.1"; or (at your option) any later version. GNU TRIE-GEN is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even thlibg++/etc/typemacros.h 600 473 0 414 4677700006 10215 #define _T(type) typeof(type) #define pointer_to(type) _T(_T(type)*) #define member_of(cls,type) _T(_T(type) cls::) #define function(res, args) _T(_T(res) args) #define _xq_yq(x,y) x ## _ ## y #define _x_y(x,y) _xq_yq(x,y) #define _gensym(stem) _x_y(stem, __LINE__) pos (point)) (re-search-forward c++-defun-header nil 'move)) (c++-end-of-defun 1)))) t )) ) (defun c++-indent-defun () "Indents the current function def, struct or class decl." (interactive) (let ((restore (poilibg++/etc/graph/test.dat 644 473 0 3432 4677700006 10463 0.000000 0.000000 0.020000 0.029996 0.040000 0.059968 0.060000 0.089892 0.080000 0.119744 0.100000 0.149500 0.120000 0.179136 0.140000 0.208628 0.160000 0.237952 0.180000 0.267084 0.200000 0.296000 0.220000 0.324676 0.240000 0.353088 0.260000 0.381212 0.280000 0.409024 0.300000 0.436500 0.320000 0.463616 0.340000 0.490348 0.360000 0.516672 0.380000 0.542564 0.400000 0.568000 0.420000 0.592956 0.440000 0.617408 0.460000 0.641332 0.480000 0.664704 0.500000 0.687500 0.520000 0.709696 0.540000 0.731268 0.560000 0.752192 0.580000 0.772444 0.600000 0.792000 0.620000 0.810836 0.640000 0.828928 0.660000 0.846252 0.680000 0.862784 0.700000 0.878500 0.720000 0.893376 0.740000 0.907388 0.760000 0.920512 0.780000 0.932724 0.800000 0.944000 0.820000 0.954316 0.840000 0.963648 0.860000 0.971972 0.880000 0.979264 0.900000 0.985500 0.920000 0.990656 0.940000 0.994708 0.960000 0.997632 0.980000 0.999404 1.000000 1.000000 1.020000 0.999404 1.040000 0.997632 1.060000 0.994708 1.080000 0.990656 1.100000 0.985500 1.120000 0.979264 1.140000 0.971972 1.160000 0.963648 1.180000 0.954316 1.200000 0.944000 1.220000 0.932724 1.240000 0.920512 1.260000 0.907388 1.280000 0.893376 1.300000 0.878500 1.320000 0.862784 1.340000 0.846252 1.360000 0.828928 1.380000 0.810836 1.400000 0.792000 1.420000 0.772444 1.440000 0.752192 1.460000 0.731268 1.480000 0.709696 1.500000 0.687500 1.520000 0.664704 1.540000 0.641332 1.560000 0.617408 1.580000 0.592956 1.600000 0.568000 1.620000 0.542564 1.640000 0.516672 1.660000 0.490348 1.680000 0.463616 1.700000 0.436500 1.720000 0.409024 1.740000 0.381212 1.760000 0.353088 1.780000 0.324676 1.800000 0.296000 1.820000 0.267084 1.840000 0.237952 1.860000 0.208628 1.880000 0.179136 1.900000 0.149500 1.920000 0.119744 1.940000 0.089892 1.960000 0.059968 1.980000 0.029996 2.000000 0.000000 .752192 1.460000 0.731268 1.480000 0.709696 1.500000 0.687500 1.520000 0.664704 1.540000 0.641332 1.560000 0.617408 1.580000 0.592956 1.600000 0.568000 1.620000 0.542564 1.640000 0.516672 1.660000 0.490348 1.680000 0.463616 1.7000libg++/etc/graph/Makefile 644 473 0 10437 4677700007 10476 # A makefile for the stuff now in libg++/etc # ------ source locations # source directory for libg++.a SRCDIR = ../../src # source include directory SRCIDIR= ../../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< RM = rm -f test: graph test.dat test2.dat ./graph -d -c 3 -g 2 -l "a diagonal line" -X "x axis" -Y "y axis" -m 1 test2.pl ./graph -d test.pl @echo use plot to look at the plot files test.pl and test2.pl libgraph.a : point.Plex.o point.XPlex.o eGetOpt.o ePlotFile.o read_data.o tick_interval.o rm -f libgraph.a ar cr libgraph.a point.Plex.o point.XPlex.o eGetOpt.o ePlotFile.o read_data.o tick_interval.o $(RANLIB) libgraph.a graph : graph.o libgraph.a $(GXX) $(GXXFLAGS) graph.o libgraph.a $(GXXLDFLAGS) -o graph point.XPlex.h : genclass point val XPlex point.Plex.h : genclass point val Plex test.dat: -echo 0 0 1 1 2 0|spline |tail -r > test.dat test2.dat: echo 0 0 >test2.dat echo 1 1 "label for 1 1" >>test2.dat echo 2 2 >>test2.dat echo 3 3 "label for 3 3" >>test2.dat echo 4 4 >>test2.dat depend:: mv Makefile Makefile.bak sed -e "/^# DO NOT DELETE/,$$ d" Makefile echo "# DO NOT DELETE" >>Makefile $(GXX) -MM *.cc >>Makefile DIST = Makefile graph.tex ChangeLog \ eGetOpt.cc read_data.cc \ eGetOpt.h read_data.h \ ePlotFile.cc tick_interval.cc \ ePlotFile.h tick_interval.h \ graph.cc point.defs.h graph.tar.Z : $(DIST) CHECKSUMS tar cfz $@ $^ CHECKSUMS CHECKSUMS : $(DIST) sum $(DIST) >CHECKSUMS dist : graph-dist.tar.Z graph-dist.tar.Z : $(DIST) -rm -rf graph-dist mkdir graph-dist ln $(DIST) graph-dist tar cfz graph-dist.tar.Z $(DIST) rm -rf graph-dist graph.shar : point.defs.h graph.cc Makefile graph.texinfo shar $^ > $@ clean: rm -f *.o *~ \#* *.bak *.pl graph.shar libgraph.a *.bak \ point.XPlex* point.Plex* realclean: clean rm -f graph # DO NOT DELETE eGetOpt.o : eGetOpt.cc eGetOpt.h ePlotFile.o : ePlotFile.cc ePlotFile.h graph.o : graph.cc read_data.h point.XPlex.h point.Plex.h point.defs.h \ eGetOpt.h ePlotFile.h tick_interval.h point.Plex.o : point.Plex.cc point.Plex.h point.defs.h point.XPlex.o : point.XPlex.cc point.XPlex.h point.Plex.h point.defs.h read_data.o : read_data.cc read_data.h point.XPlex.h point.Plex.h \ point.defs.h tick_interval.o : tick_interval.cc tick_interval.h point.Plex* realclean: clean rm -f graph # DO NOT DELETE eGetOpt.o : eGetOpt.cc eGetOpt.h ePlotFile.o : ePlotFile.cc ePlotFile.h graph.o : graph.cc read_data.h point.XPlex.h point.Plex.h point.defs.h \ eGetOpt.h ePlotFlibg++/etc/graph/graph.tex 644 473 0 30005 4677700007 10652 \input texinfo @c -*-texinfo-*- @setfilename graph.info @settitle graph @ifinfo This file documents graph, a utility for creating plot files. Copyright @copyright{} 1989 Free Software Foundation, Inc. @end ifinfo @titlepage @sp 10 @center @titlefont{graph} @sp 2 @center A utility for creating plot files @sp 2 @vskip 0pt plus 1filll Copyright @copyright{} 1989 Free Software Foundation @end titlepage @node Top, Options, , (dir) @chapter The @code{graph} Utility @code{graph} is a utility for creating plots from data. It reads ascii data and writes a plot with axes and labels. You can specify labels and ranges for the axes, and you can set the sizes and position of the plot on the page. Each invocations of graph produces a single box with a set of axes and data draw within. You can place an arbitrary number of plots on the page by concatenating the plot output of each invocation.@refill @menu * Options:: Command line options for graph. * Graph Examples:: How to use graph. * plot2ps:: A GNU plot to postscript conversion utility. @end menu @chapter Options at a glance @table @samp @item Option: Description: @item -C print copyright notice @item -D binary double precision data @item -E use extended plot file format @item -H CHARACTER_HEIGHT fractional height of characters @item -I binary integer data @item -M [x|y] MARGIN amount of margin between data and x or y axes. @item -N TICKS number of tick marks on each axis @item -P SIZE plot file coordinate range @item -S SYMBOL_NUMBER SYMBOL_SIZE draw symbols at each point @item -T TICK_SIZE fractional size of tick marks @item -W CHARACTER_WIDTH fractional width of characters @item -X X_LABEL label printed below the x axis @item -Y Y_LABEL label printed right of the y axis @item -a STEP_SIZE LOWER_LIMIT generate abscissa, read only y values @item -b break lines whenever x decreases @item -c POINT_LABEL default label printed at each point @item -d print debugging information @item -g GRID_STYLE draw a grid in the plot @item -h HEIGHT fractional height of the plot @item -l TOP_LABEL label printed above the plot @item -m LINE_MODE solid and dashed lines @item -r RIGHT move plot right by fractional amount @item -s save the screen - do not erase @item -t transpose x and y axes @item -u UP move plot up by fractional amount @item -w WIDTH fractional width of the plot @item -x l LOWER_LIMIT UPPER_LIMIT log scale, axis limits @item -y l LOWER_LIMIT UPPER_LIMIT log scale, axis limits @item -z do not read data from standard input @end table @node Options, Graph Examples, Top, Top @chapter Command Line Options The following table describes each of the command line arguments to graph. Each option which takes an argument is followed by the type and default values of the argument in parentheses. @table @samp @item -C Print out the GNU copyright notice.@refill @item -D Read double precision binary data rather than ascii data. Since @code{graph} is generally I/O bound, this can decrease execution time.@refill @item -E Use an extended plot file format. This provides automatic adjustment of labels with respect to tick marks. The @samp{-H} and @samp{-W} options are ignored if @samp{-E} is specified. You will need the GNU plot utility @code{plot2ps} in oder to print the output.@refill @item -H (double, default .03) The fractional height of printed characters. This value is used to adjust location of labels with respect to the tick marks.@refill @item -I Read integer binary data rather than ascii data.@refill @item -M @samp{[x|y]} @var{margin} (double, default 0 for x and .05 for y) @var{margin} is the fractional amount of margin between the data and the horizontal or vertical edges of the box. A value of .05 for y produces a space which is 5% of the height of the box, placed above and below the data.@refill @item -M amount of margin between data and x or y axes. @item -N @var{ticks} (integer, default 5) @var{ticks} is the minimum number of tick marks for each axis. @code{graph} tries to pick as few digits as possible for tick mark labels and uses at least this many tick marks.@refill @item -P @var{size} (integer, default 4096) @var{size} is the upper limit on coordinate values in the plot file @code{graph} creates. For devices with higher resolution, this value can be increased. A value of 4096 is sufficient for 300 dot per inch devices such as laser writers. This limit on the values of coordinates (0 to @var{size}) output by @code{graph} is rigidly enforced to prevent unpredictable behaviors by device drivers such as @code{plot}.@refill @item -S @var{symbol_number} @var{symbol_size} (integer and float, defaults 0 and 0.01) Draw a symbol at each point in the data. @var{symbol_number} specifies the shape of the symbol according to the following table and @var{symbol_size} specifies the fractional size of the symbol with respect to the height and width of the plot.@refill @table @asis @item 0 no symbol @item 1 plus sign @item 2 cross @item 3 diamond @end table @item -T @var{tick_size} (float, default .01) @var{tick_size} is the fractional size of the tick marks on each axis. A value of 1.0 produces tick marks on the x (y) axis whose length is equal to the width (height) of the plot.@refill @item -W (double, default .02) The fractional width of printed characters. Like the @samp{-H} option, this value is used to adjust location of labels with respect to the tick marks.@refill @item -X @var{x_label} (string, default blank) @var{x_label} is a label printed below the x axis.@refill @item -Y @var{y_label} (string, default blank) @var{y_label} is a label printed to the right of the y axis.@refill @item -a @var{step_size} @var{lower_limit} (floats, defaults 1 and 0) Automaticly generate abscissa (x) values. This option specifies that the data contains only ordinate (y) values. @var{step_size} specifies the interval between neighboring points and @var{lower_limit} specifies the first abscissa (x) value.@refill @item -b Break the lines in the graph whenever the abscissa (x) values decrease. Several curves with monotonically increasing abscissa values can be concatenated and fed to graph using this option.@refill @item -c @var{point_label} (string, default blank) @var{point_label} is the default label placed at each point in the plot when none is read from the input for that point. That is, labels read from the input are printed instead of the default whenever they are present.@refill @item -d Debugging information, including the data read in, is sent to the standard error output. This is useful for double checking binary data files.@refill @item -g @var{grid_style} (integer, default 1) @var{grid_style} specifies the type of box framing the plot and whether grid lines are drawn inside the box.@refill @table @asis @item 0 no box around plot, no axes, no labels. @item 1 box around plot, axes with tick marks and labels. @item 2 box containing a grid and axes with tick marks and labels. @end table @item -h @var{height} (float, default 0.8) @var{height} specifies the fractional height of the plot with respect to the height of the plotting area. A value of 1.0 will produce a box which fills the available area. Note that the tick marks and labels are outside this area so that values less than 1.0 are generally used.@refill @item -l @var{top_label} (string, default blank) @var{top_label} is a label placed above the plot.@refill @item -m @var{line_mode} (integer, default 0) @var{line_mode} specifies the mode (or style) of lines drawn between data points.@refill @table @asis @item 0 solid @item 1 longdashed @item 2 dotted @item 3 disconnected @item 4 dotdashed @item 5 shortdashed @end table @item -r @var{right} (float, default 0.1) Move the plot to the right by a fractional amount @var{right} with respect to the width of the plotting area. This produces a margin on the left hand side of the plot. A value of 0.5 will produce a margin half the width of the available area. Note that the tick marks and labels are drawn in the margin.@refill @item -s Save the screen. This option prevent graph from erasing the previous contents of the graphics window or device.@refill @item -t Transpose the axes and axis labels. This option flips the plot over by interchanging x and y values and labels.@refill @item -u @var{up} (float, default 0.1) Move the plot up by a fractional amount @var{up} with respect to the height of the plotting area. This produces a margin below the plot. A value of 0.5 will produce a margin half the height of the available area. Note that the tick marks and labels are drawn in the margin.@refill @item -w @var{width} (float, default 0.8) @var{width} specifies the fractional width of the plot with respect to the width of the plotting area. A value of 1.0 will produce a box which fills the available area. Note that the tick marks and labels are outside this area, so values less than 1.0 are generally used.@refill @item -x @samp{l} @var{lower_limit} @var{upper_limit} (char, floats) @samp{l} is optional and specifies that a logarithmic scale be used for the x axis, by default a linear scale is used. The arguments @var{lower_limit} and @var{upper_limit} specify the limits of the x axis. By default the upper and lower limits are taken from the data.@refill @item -y @samp{l} @var{lower_limit} @var{upper_limit} The arguments specify the scale and limits of the y axis as those do for the x axis above.@refill @item -z Do not read data from the standard input. You can specify input files on the command line. @code{graph} prints the file names and point numbers when it encounters error in ascii input files. If input files are named and contain one coordinate per line in the file axis whose length is equal to the width (height) of the plot you can use the emacs @code{next-error} function to locate the source of the error.@refill @end table @node Graph Examples, plot2ps, Options, Top @chapter @code{graph} Examples @section The format of input to @code{graph} @code{graph} reads in ascii data. Most often, the data is in the form of pairs of x and y values:@refill @example 0.0 0.0 1.0 0.2 2.0 0.0 3.0 0.4 4.0 0.2 5.0 0.6 @end example You can add labels to specific data points by appending a string after the y coordinate. The label ends at the end of the line:@refill @example 3.0 0.4 this is a label for point (3.0, 0.4). @end example Using the @samp{-b} option, you can put more than one data set in the input as long as each is monotonic in x values and decreases from the end of one set to the start of the next:@refill @example 0.0 0.0 first data set 2.0 0.0 4.0 0.2 0.0 0.1 second data set 2.0 0.2 4.0 0.3 @end example If your data contains only y values which are equally sampled along the x axis, you can use the @samp{-a} option to specify the x axis values implicitly.@refill @example 0.0 0.1 0.2 label for point (2.0, 0.2) 0.3 0.2 0.3 @end example @section How to put multiple plots on one page The command @example graph -h .4 -w .4 -r .1 -u .1 < ascii_data_file_1 > plot_file @end example will put a single box containing the plot in the lower left hand quarter of the page. You can add another plot to the upper left hand corner of the page using the command @example graph -h .4 -w .4 -r .1 -u .6 < ascii_data_file_2 >> plot_file @end example Likewise you can add plots to the right hand side of the page using @example graph -h .4 -w .4 -r .6 -u .1 < ascii_data_file_3 >> plot_file graph -h .4 -w .4 -r .6 -u .6 < ascii_data_file_4 >> plot_file @end example @node plot2ps,, Graph Examples, Top @section The @code{plot2ps} Utility @code{plot2ps} is a utility for converting Unix plot files into postscript. The @code{plot2ps} utility reads plotting commands from named files or the standard input and writes postscript to the standard output. You can then print the postscript output on a printer, or edit it using the @code{idraw} graphics editor. You can also easily include the output in LaTeX documents using the @code{dvi2ps} utility and the LaTeX command @code{psfig}.@refill The source code and documentation for @code{plot2ps} and a more complete description of this are available via anonymous ftp from qed.rice.edu (128.42.4.38) in the directory @file{/pub}. @contents @bye or the standard input and writes postscript to the standard output. You can then print the postscript output on a printer, or edit it using the @code{idraw} graphics editor. You can also easily include the output in LaTeX documents using the @code{dvi2ps} utility and the LaTeX command @code{psfig}.@refill The source code and documentation for @code{plot2ps} and a more complete description of this are available via anonymous ftp from qed.rice.edu (128.42.4.38) in the directory @file{/pub}. @contents libg++/etc/graph/ChangeLog 644 473 0 4527 4677700007 10573 Wed Jan 3 12:43:46 1990 Doug Lea (dl at g.oswego.edu) * graph.cc: replaced sprintf calls with dtoa, since sprintf is apparently pretty broken on some systems. * eGetOpt, ePlotFile: explicilty list constructrs, since g++ no longer allows inheritence of ctors. Sun Dec 3 21:21:17 1989 Carey R. Murphey (rich at kalliope) * graph.c: add margins beteen edges of the data and the box only if the scale is not logarithmic. Otherwise the additional margin could cause the value at the end of the axis to be negative. Wed Nov 8 20:59:38 1989 Carey R. Murphey (rich at kalliope) * The -c option was incompatible with other versions of graph. Changed graph.cc to use this option to specify a default label to be printed at each data point. Symbols can be specified now using the `-S' option. * Added the option `-z' to prevent graph from reading the standard input. * split out read_data, tick_interval, eGetOpt, and ePlotFile into separate files. Had to change the arguments to read_data to include what used to be passed through global data. * graph.cc: changed expressions using ?: to use >? or > p.x >> WS; if (switch_symbols && (p.x < prev_x)) symbol_number++; prev_x = p.x; in >> p.y; if (!in.good ()) // if we read x but not y complain. { char *line; in.clear (); in.gets (&line); // if the input contains one coordinate per line // you win here --- emacs can find the source // line from this error message. cerr << in.name () << ":" << 2 + pplex.high() << ": unable to read the" sp 2 + pplex.high() << "th y coordiate.\n"; if (strlen (line)) cerr << in.name () << ":" << 2 + pplex.high() << ": unexpected `" << line << "'\n"; break; } in >> WS; // skip white space after y coordinate p.label = (char *) 0; // by default there is no label in.get (next_char); // look ahead for a label if (in.good ()) { in.unget (next_char); if (!isdigit (next_char) // if a lable is found && (next_char != EOF) && (next_char != '.') && (next_char != '+') && (next_char != '-')) { in.gets (&p.label); // store it with x and y } in >> WS; // skip white space after label } p.symbol = symbol_number; pplex.add_high (p); } } return; } void read_data (File& in, pointXPlex &pplex, int auto_abscissa, double x_start, double delta_x, int &symbol_number, data_type input_data, int switch_symbols) { point p; // the point we are currently reading in. p.label = (char *) 0; // binary files contain no labels. double prev_x = -HUGE; // the previous x value. if (auto_abscissa) x_start -= delta_x; if (input_data == DOUBLE) { // input contains binary double precision while (in.good ()) { if (auto_abscissa) p.x = x_start = x_start + delta_x; else { in.read (&p.x, sizeof(p.x), 1); if (switch_symbols && (p.x < prev_x)) symbol_number++; prev_x = p.x; } in.read (&p.y, sizeof(p.y), 1); p.symbol = symbol_number; if (in.good ()) pplex.add_high (p); } } if (input_data == INT) { // input contains binary integers int i; while (in.good ()) { if (auto_abscissa) p.x = x_start = x_start + delta_x; else { in.read (&i, sizeof(i), 1); p.x = i; if (switch_symbols && (p.x < prev_x)) symbol_number++; prev_x = p.x; } in.read (&p.y, sizeof(p.y), 1); p.symbol = symbol_number; if (in.good ()) pplex.add_high (p); } } return; } if (in.good ()) pplex.add_high (p); } } if (input_data == INT) { // input contains binary integers int i; while (in.good ()) { if (auto_abscissa) p.x = x_start = x_start + delta_x; else { in.read (&i, sizeof(i), 1); p.x = i; if (switch_symbols && (p.x #include // eGetOpt is a subclass of GetOpt which provides functions for // handling arguments to the options. class eGetOpt : public GetOpt { public: eGetOpt (int argc, char **argv, char *optstring) : GetOpt(argc,argv,optstring) {} // first_char returns the first character of the argument. int first_char () { return nargv[optind][0];}; // next_arg looks at next argument for an interger, double or string // depending on the type of argument given to it. If the correct type is // found, the value is set and next_arg returns 1. If the type is not // correct, next_arg returns 0. // double arguments start with a digit, plus, minus or period. // integer arguments start with a digit. // String arguments have no restriction. // If the next argument is an integer, set the reference variable to it // and increment the index to the options. Return 1 if an integer is // found, else return 0. int next_arg (int &i); int next_arg (double &d); int next_arg (String &s); }; #endif lue is set and next_arg returns 1. If the type is not // correct, next_arg returns 0. // double arguments start with a digit, plus, minus or period. // integer arguments start with a digit. // String arguments have no restriction. // If the next argument is an integer, set the reference variable to it // and increment the index to the options. Return 1 if an integer is // found, else libg++/etc/graph/read_data.h 644 473 0 1736 4677700010 11067 // -*- C++ -*- // READ_DATA reads ascii (or binary) data from an istream (or File) of // coordinates and labels. It passes back the array of points (x, y, // and label) containing the data. #ifndef read_data_h #pragma once #define read_data_h 1 #include #include #include #include "point.XPlex.h" #ifdef HUGE #undef HUGE #endif #define HUGE 1e37 #define sp <<" "<< #define nl <<"\n" // data_type value indicates the type of data present in the input files. typedef enum { ASCII, DOUBLE, INT } data_type; overload read_data; // read ascii data from a stream void read_data (istream& in, pointXPlex &pplex, int auto_abscissa, double x_start, double delta_x, int &symbol_number, data_type input_data, int switch_symbols); // read binary data from a file void read_data (File& in, pointXPlex &pplex, int auto_abscissa, double x_start, double delta_x, int &symbol_number, data_type input_data, int switch_symbols); #endif the input files. typedef enum { ASlibg++/etc/graph/ePlotFile.cc 644 473 0 433 4677700010 11155 #include "ePlotFile.h" ePlotFile& ePlotFile:: alabel (alabel_xadj x_adjust, alabel_yadj y_adjust, char *s) { cmd ('T'); cmd (x_adjust); cmd (y_adjust); (PlotFile*)(this)->operator <<(s); // workaround -dl (PlotFile*)(this)->operator <<("\n"); return *this; }; ata from a file void read_data (File& in, pointXPlex &pplex, int auto_abscissa, double x_start, double delta_x, int &symbol_number, data_type input_data, int switch_symbols); #endif the input files. typedef enum { ASlibg++/etc/graph/tick_interval. 644 473 0 725 4677700011 11627 #include "math.h" // The resolution of the output device is much less than seven digits. // A_HAIR_MORE is used to ingore the effects of round off error which should // occur in the last few of the 16 digits. #define A_HAIR_MORE 1.0000001 // TICK_INTERVAL returns the step size which can be used to put a // specified NO_OF_TICKS beteen the specified UPPER_LIMIT and LOWER_LIMIT. double tick_interval (double no_of_ticks, double &lower_limit, double &upper_limit); #endif the input files. typedef enum { ASlibg++/etc/graph/ePlotFile.h 644 473 0 2001 4677700010 11030 #ifndef ePlotFile_h #pragma once #define ePlotFile_h 1 #include // ePlotFile is an extended plot file class which has adjusted labels. // put the left center or right edge of the text at the current point. typedef enum alabel_xadj { LEFT_JUSTIFY = 'l', CENTER_JUSTIFY = 'c', RIGHT_JUSTIFY = 'r'}; // put the top center or bottom edge of the text at the current point. typedef enum alabel_yadj { BOTTOM_FLUSH = 'b', CENTER_FLUSH = 'c', TOP_FLUSH = 't' }; class ePlotFile : public PlotFile { public: ePlotFile() : PlotFile() {} ePlotFile(const char* filename, io_mode m, access_mode a) :PlotFile(filename, m, a) {} ePlotFile(const char* filename, const char* m) :PlotFile(filename, m) {} ePlotFile(int filedesc, io_mode m = io_writeonly) :PlotFile(filedesc, m) {} ePlotFile(FILE* fileptr) : PlotFile(fileptr) {} ePlotFile& alabel (alabel_xadj x_adjust, alabel_yadj y_adjust, char *s); }; #endif ic: ePlotFile() : PlotFile() {} ePlotFile(const char* filename, io_mode m, access_mode a) :PlotFile(filename, m, a) {} ePlotFile(const char* filename, const char* m) :PlotFile(filename, m) {} ePlotFile(int filedesc, io_mode m = io_writeonly) :PlotFile(filedesc, m) {} ePlotFile(FILE* fileptr) : PlotFile(fileptr) {} ePlotFile& alabel (alabel_xadj x_adjust, alabel_yadj y_adjust, char *s); }; #endiflibg++/etc/graph/graph.cc 644 473 0 51250 4677700011 10437 // graph.cc --- graph reads data and writes out a plot file. const char *copyright_notice = "\ Copyright (C) 1989 Free Software Foundation \n\ \n\ This file is part of GNU CC. \n\ \n\ GNU CC is distributed in the hope that it will be useful, \n\ but WITHOUT ANY WARRANTY. No author or distributor \n\ accepts responsibility to anyone for the consequences of using it \n\ or for whether it serves any particular purpose or works at all, \n\ unless he says so in writing. Refer to the GNU CC General Public \n\ License for full details. \n\ \n\ Everyone is granted permission to copy, modify and redistribute \n\ GNU CC, but only under the conditions described in the \n\ GNU CC General Public License. A copy of this license is \n\ supposed to have been given to you along with GNU CC so you \n\ can know your rights and responsibilities. It should be in a \n\ file named COPYING. Among other things, the copyright notice \n\ and this notice must be preserved on all copies. \n\ "; #include "read_data.h" #include "eGetOpt.h" #include "ePlotFile.h" #include "tick_interval.h" const char *usage_message = "\ [options...]\n\ \n\ Option: Description:\n\ -C print copyright notice\n\ -D binary double precision data\n\ -E use extended plot file format\n\ -H CHARACTER_HEIGHT fractional height of characters\n\ -I binary integer data\n\ -M [x|y] MARGIN margin between data and edges of box\n\ -N TICKS number of tick marks on each axis\n\ -P SIZE plot file coordinate range\n\ -S SYMBOL_NUMBER SYMBOL_SIZE draw symbols at each point\n\ -T TICK_SIZE fractional size of tick marks\n\ -W CHARACTER_WIDTH fractional width of characters\n\ -X X_LABEL label printed below the x axis\n\ -Y Y_LABEL label printed right of the y axis\n\ -a STEP_SIZE LOWER_LIMIT generate abcissa, read only y values\n\ -b break lines whenever x decreases\n\ -c POINT_LABEL default label printed at each point\n\ -d print debugging information\n\ -g GRID_STYLE draw a grid in the plot\n\ -h HEIGHT fractional height of the plot\n\ -l TOP_LABEL label printed above the plot\n\ -m LINE_MODE solid and dashed lines\n\ -r RIGHT move plot right by fractional ammount\n\ -s save the screen - do not erase\n\ -t transpose x ans y axes\n\ -u UP move plot up by fractional ammount\n\ -w WIDTH fractional width of the plot\n\ -x l LOWER_LIMIT UPPER_LIMIT log scale, axis limits\n\ -y l LOWER_LIMIT UPPER_LIMIT log scale, axis limits\n\ -z do not read data from standard input\n\ "; // Here are the command line option data and flags: String default_label; // default label at each point. String top_label; // label above the plot. String x_label; // x axis label String y_label; // y axis label data_type input_data = ASCII; // the type of data to be read in. double char_height = .03; // fractional height of printed characters double char_width = .02; // fractional width of printed characters double height = .8; // fraction height of the plot. double lower_limit = 0.; // lower limit in x for generated values double no_of_ticks = 5.; // number of tick marks on the axes. double right = .1; // the fractional margin on the right side. double size_of_ticks = .01; // fractional size of the tick marks. double spacing = 1.; // stepsize for equally spaced generated values double symbol_size = .01; // index of symbol drawn at each point. double up = .1; // the fractional margin above the plot. double width = .8; // fraction width of the plot. double x_lower_limit = HUGE; // HUGE means get it from the data double x_margin = 0.0; // fractional margin between data and box double x_upper_limit = HUGE; // HUGE means get it from the data double y_lower_limit = HUGE; // HUGE means get it from the data double y_margin = 0.05; // fractional margin between data and box double y_upper_limit = HUGE; // HUGE means get it from the data int abcissa_flag = 0; // nonzero means generate x axiz values int break_flag = 0; // break the line whenever x decreases. int debug_flag = 0; // verbose debugging output. int extended_plot_format = 0; // nonzero means use adjusted labels. int grid_style = 1; // style of box and or axes. int line_style = 0; // the type of line drawn to connect points. int no_standard_input = 0; // nonzero means do not read from standard input int plot_size = 4096; // upper limit of plot file coordinates int save_screen_flag = 0; // nonzero means do not erase before plotting. int switch_style = 0; // switch line style for each new curve int switch_symbols = 0; // switch symbols when starting each new curve int symbol_number = 0; // index of symbol drawn at each point. int transpose_axes_flag = 0; // nonzero means interchange x and y axes. int x_log_scale = 0; // the x axis is log scale int y_log_scale = 0; // the y axis is log scale // the names of line styles recognized in the unix plot file convention. const int max_line_style = 5; char *line_style_name[max_line_style+1] = { "solid", "longdashed", "dotted", "disconnected", "dotdashed", "shortdashed" }; // This is all the data describing how to draw the symbols. typedef enum op {END, CONT, MOVE, CIRCLE}; // a graphic operation struct coord // a component coordintate within a symbol { double x, y; // fractional coordinates op operation; // the type of graphic }; struct coord symbol[][10] = // set of symbols { { // no symbol (blank) { .0, .0, END} }, { // plus sign { -.5, .0, MOVE}, { .5, .0, CONT}, { .0, -.5, MOVE}, { .0, .5, CONT}, { .0, .0, END} }, { // cross { -.5, -.5, MOVE}, { .5, .5, CONT}, { .5, -.5, MOVE}, { -.5, .5, CONT}, { .0, .0, END} }, { // diamond { -.5, .0, MOVE}, { .0, .5, CONT}, { .5, .0, CONT}, { .0, -.5, CONT}, { -.5, .0, CONT}, { .0, .0, END} }, { // square { -.5, -.5, MOVE}, { -.5, .5, CONT}, { .5, .5, CONT}, { .5, -.5, CONT}, { -.5, -.5, CONT}, { .0, .0, END} }, { // triangle { -.5, -.5, MOVE}, { .0, .86603, CONT}, { .5, -.5, CONT}, { -.5, -.5, CONT}, { .0, .0, END} }, { // circle { .5, .0, CIRCLE}, { .0, .0, END} }, { // add more symbols here... { .0, .0, END} } }; // Here are the functions for transforming and clipping. inline int px (double t) // transform fractional x to plot x { return (int) (plot_size * (width * t + right)); // should we round rather than // truncate here? } inline int py (double t) // transform fractional x to plot x { return (int) (plot_size * (height * t + up)); } inline int clip (int coord) { return (coord >? 0) = xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax); } int main (int argc, char **argv) { eGetOpt getopt (argc, argv, "CDEH::IN::P::ST::W::X::Y::a::bc::dg::h::l::m::r::stu::vw::x::y::z"); int option_char; int error_occurred = 0; // non zero for a bad command line option while (EOF != (option_char = getopt ())) switch (option_char) { case 'C': cerr << copyright_notice; break; case 'D': input_data = DOUBLE; break; case 'E': extended_plot_format++; break; case 'H': getopt.next_arg (char_height); break; case 'I': input_data = INT; break; case 'M': if ('x' == getopt.first_char()) {getopt.optind++; getopt.next_arg (x_margin);} break; if ('y' == getopt.first_char()) {getopt.optind++; getopt.next_arg (y_margin);} break; case 'N': getopt.next_arg (no_of_ticks); break; case 'P': getopt.next_arg (plot_size); break; case 'S': getopt.next_arg (symbol_number); getopt.next_arg (symbol_size); break; case 'T': getopt.next_arg (size_of_ticks); break; case 'W': getopt.next_arg (char_width); break; case 'X': getopt.next_arg (x_label); break; case 'Y': getopt.next_arg (y_label); break; case 'a': abcissa_flag++; getopt.next_arg (spacing); getopt.next_arg (lower_limit); break; case 'b': break_flag++; break; case 'c': getopt.next_arg (default_label); break; case 'd': debug_flag++; break; case 'g': getopt.next_arg (grid_style); break; case 'h': getopt.next_arg (height); break; case 'l': getopt.next_arg (top_label); break; case 'm': getopt.next_arg (line_style); break; case 'r': getopt.next_arg (right); break; case 's': save_screen_flag++; break; case 't': transpose_axes_flag++; break; case 'u': getopt.next_arg (up); break; case 'v': cerr << "graph version 0.\n"; break; case 'w': getopt.next_arg (width); break; case 'x': if ('l' == getopt.first_char()) {x_log_scale++; getopt.optind++;} getopt.next_arg (x_lower_limit); getopt.next_arg (x_upper_limit); break; case 'y': if ('l' == getopt.first_char()) {y_log_scale++; getopt.optind++;} getopt.next_arg (y_lower_limit); getopt.next_arg (y_upper_limit); break; case 'z': no_standard_input++; break; case '?': error_occurred++; } if (error_occurred) cerr << "usage" sp argv[0] sp usage_message; // Complain if the plot does not fits on page if (up < 0.) cerr << "Warning: the plot may extend below the bottom of the page.\n"; if (up + height > 1.) cerr << "Warning: the plot may extend above the top of the page.\n"; if (right < 0.) cerr << "Warning: the plot may extend beyond the left edge of the page.\n"; if (right + width > 1.) cerr << "Warning: the plot may extend beyond the right edge of the page.\n"; // now we start reading in all the data. pointXPlex point; // all the data is held in an array of points // read data from standard input. File input_file; if (! no_standard_input) { if (input_data == ASCII) { // ascii data read_data (cin, point, abcissa_flag, lower_limit, spacing, symbol_number, input_data, switch_symbols); } else { // binary data input_file.open (stdin); read_data (input_file, point, abcissa_flag, lower_limit, spacing, symbol_number, input_data, switch_symbols); } } // read data files specified on command line. int i; for (i=getopt.optind; i point[i].x) xmin = point[i].x; if (ymin > point[i].y) ymin = point[i].y; if (xmax < point[i].x) xmax = point[i].x; if (ymax < point[i].y) ymax = point[i].y; } // add margins beteen edges of the data and box if range is nonzero and // the scale is not logarithmic. if (!y_log_scale) { double tmp = (ymax - ymin); ymax += y_margin * tmp; ymin -= y_margin * tmp; } if (!x_log_scale) { double tmp = (xmax - xmin); xmax += x_margin * tmp; xmin -= x_margin * tmp; } } // use limits specified on the command line if present. if (x_lower_limit != HUGE) xmin = x_lower_limit; if (y_lower_limit != HUGE) ymin = y_lower_limit; if (x_upper_limit != HUGE) xmax = x_upper_limit; if (y_upper_limit != HUGE) ymax = y_upper_limit; // make sure that 0 is not in range if we are using a log scale. if ( (x_log_scale && (xmin <= 0.) && (xmax >= 0.)) || (y_log_scale && (ymin <= 0.) && (ymax >= 0.))) { cerr << "the lower bound on x is" sp xmin nl; cerr << "the upper bound on x is" sp xmax nl; cerr << "the lower bound on y is" sp ymin nl; cerr << "the upper bound on y is" sp ymax nl; cerr << "Zero cannot lie between an upper and lower bound" nl "if you use a log scale." nl; exit (-1); } if (x_log_scale) { log_xmin = log (xmin); log_xmax = log (xmax); } if (y_log_scale) { log_ymin = log (ymin); log_ymax = log (ymax); } // We have the limits, Now plot. plot_file.space (0, 0, plot_size, plot_size); // draw a box around the data. if (grid_style) plot_file.box (px (0.), py (0.), px (1.), py (1.)); char tick_label[32]; // tick lables are less than 16 digits long. // draw x tick marks. if (grid_style) { // draw labels and ticks on x axis. double x_tick = tick_interval (no_of_ticks, xmin, xmax); double x_tick_value = x_tick * (x_tick > 0. ? ceil (xmin * A_HAIR_MORE / x_tick) : floor (xmin * A_HAIR_MORE / x_tick)); while (x_tick_value <= xmax * A_HAIR_MORE) { // tick marks on axes. plot_file.line (px (fx (x_tick_value)), py (0.), px (fx (x_tick_value)), py (-1. * size_of_ticks)); plot_file.line (px (fx (x_tick_value)), py (1.), px (fx (x_tick_value)), py (1. + size_of_ticks)); strcpy(tick_label, dtoa(x_tick_value)); plot_file.move (px (fx (x_tick_value) - (extended_plot_format ? 0 : .5 * char_width * strlen (tick_label))), py (-1. * size_of_ticks - (extended_plot_format ? 0 : 1. * char_height))); if (extended_plot_format) plot_file.alabel (CENTER_JUSTIFY, TOP_FLUSH, tick_label); else plot_file.label (tick_label); if (grid_style == 2) { // grid across box. plot_file.linemod ("shortdashed"); plot_file.line (px (fx (x_tick_value)), py (0.), px (fx (x_tick_value)), py (1.)); plot_file.linemod ("solid"); } if ((.5 < fx (x_tick_value + x_tick)) && x_label.length ()) { // put the label between tick marks plot_file.move (px (fx (x_tick_value + x_tick / 2. - (extended_plot_format ? 0 : .5 * char_width * x_label.length ()))), py (-1. * size_of_ticks - (extended_plot_format ? 0 : 2. * char_height))); if (extended_plot_format) plot_file.alabel (CENTER_JUSTIFY, TOP_FLUSH, x_label); else plot_file.label (x_label); x_label = ""; } x_tick_value += x_tick; if (fabs (x_tick_value / x_tick) < 1e-7) x_tick_value = 0.; } // draw labels and ticks on y axis. double y_tick = tick_interval (no_of_ticks, ymin, ymax); double y_tick_value = y_tick * (y_tick > 0. ? ceil (ymin * A_HAIR_MORE / y_tick) : floor (ymin * A_HAIR_MORE / y_tick)); while (y_tick_value <= ymax * A_HAIR_MORE) { // draw tick marks on axes plot_file.line (px (0.), py (fy (y_tick_value)), px (-1. * size_of_ticks), py (fy (y_tick_value))); plot_file.line (px (1.), py (fy (y_tick_value)), px (1. + size_of_ticks), py (fy (y_tick_value))); plot_file.move (px (1. + 2. * size_of_ticks), py (fy (y_tick_value) - .5 * (extended_plot_format ? 0 : char_height))); if (extended_plot_format) plot_file.alabel (LEFT_JUSTIFY, CENTER_FLUSH, strcpy (tick_label, dtoa(y_tick_value))); else plot_file.label (strcpy (tick_label, dtoa(y_tick_value))); if (grid_style == 2) { // draw grid within box. plot_file.linemod ("shortdashed"); plot_file.line (px (0.), py (fy (y_tick_value)), px (1.), py (fy (y_tick_value))); plot_file.linemod ("solid"); } if ((.5 < fy (y_tick_value + y_tick)) && y_label.length ()) { // put the label between tick marks plot_file.move (px (1. + size_of_ticks), py (fy (y_tick_value + y_tick / 2.))); if (extended_plot_format) plot_file.alabel (LEFT_JUSTIFY, CENTER_FLUSH, y_label); else plot_file.label (y_label); y_label = ""; } y_tick_value += y_tick; if (fabs (y_tick_value / y_tick) < 1e-7) y_tick_value = 0.; } if (top_label.length ()) // put label above plot. { plot_file.move (px (.5 - (extended_plot_format ? 0 : .5 * char_width * top_label.length ())), py (1. + size_of_ticks)); if (extended_plot_format) plot_file.alabel (CENTER_JUSTIFY, BOTTOM_FLUSH, top_label); else plot_file.label (top_label); } } if (line_style) // set style of lines connecting data points. plot_file.linemod (line_style_name[line_style #include /* Define the symbol ETAGS to make the program "etags", which makes emacs-style tag tables by default. Define CTAGS to make the program "ctags" compatible with the usual one. Define neither one to get behavior that depends on the name with which the program is invoked (but we don't normally compile it that way). */ /* On VMS, CTAGS is not useful, so always do ETAGS. */ #ifdef VMS #ifndef ETAGS #define ETAGS #endif #endif /* Exit codes for success and failure. */ #ifdef VMS #define GOOD (1) #define BAD (0) #else #define GOOD (0) #define BAD (1) #endif #define reg register #define logical char #define TRUE (1) #define FALSE (0) #define iswhite(arg) (_wht[arg]) /* T if char is white */ #define begtoken(arg) (_btk[arg]) /* T if char can start token */ #define intoken(arg) (_itk[arg]) /* T if char can be in token */ #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */ #define max(I1,I2) (I1 > I2 ? I1 : I2) /* cause token checking for typedef, struct, union, enum to distinguish keywords from identifier-prefixes (e.g. struct vs struct_tag). */ #define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len)))) struct nd_st { /* sorting structure */ char *name; /* function or type name */ char *file; /* file name */ logical f; /* use pattern or line no */ int lno; /* line number tag is on */ long cno; /* character number line starts on */ char *pat; /* search pattern */ logical been_warned; /* set if noticed dup */ struct nd_st *left,*right; /* left and right sons */ }; long ftell(); typedef struct nd_st NODE; int number; /* tokens found so far on line starting with # (including #) */ logical gotone, /* found a func already on line */ /* boolean "func" (see init) */ _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177]; /* typedefs are recognized using a simple finite automata, * tydef is its state variable. */ typedef enum {none, begin, tag_ok, middle, end } TYST; TYST tydef = none; char searchar = '/'; /* use /.../ searches */ int lineno; /* line number of current line */ long charno; /* current character number */ long linecharno; /* character number of start of line */ char *curfile, /* current input file name */ *outfile= 0, /* output file */ *white = " \f\t\n", /* white chars */ *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */ *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */ *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */ *notgd = ",;"; /* non-valid after-function chars */ int file_num = 0; /* current file number */ int aflag = 0; /* -a: append to tags */ int tflag = 0; /* -t: create tags for typedefs */ int uflag = 0; /* -u: update tags */ int wflag = 0; /* -w: suppress warnings */ int vflag = 0; /* -v: create vgrind style index output */ int xflag = 0; /* -x: create cxref style output */ int eflag = 0; /* -e: emacs style output */ int pflag = 0; /* -p: assume *.[ch] files are C++ */ /* Name this program was invoked with. */ char *progname; FILE *inf, /* ioptr for current input file */ *outf; /* ioptr for tags file */ NODE *head; /* the head of the sorted binary tree */ char *savestr(); char *savenstr (); char *rindex(); char *index(); char *concat (); void initbuffer (); long readline (); char *malloc(), *realloc(); char *xmalloc(), *xrealloc(); /* A `struct linebuffer' is a structure which holds a line of text. `readline' reads a line from a stream into a linebuffer and works regardless of the length of the line. */ struct linebuffer { long size; char *buffer; }; struct linebuffer lb, lb1; #if 0 /* VMS now provides the `system' function. */ #ifdef VMS #include void system (buf) char *buf; { struct dsc$descriptor_s command = { strlen(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf }; LIB$SPAWN(&command); } #endif /* VMS */ #endif /* 0 */ main(ac,av) int ac; char *av[]; { char cmd[100]; int i; int fflag = 0; char *this_file; #ifdef VMS char got_err; extern char *gfnames(); extern char *massage_name(); #endif progname = av[0]; #ifdef ETAGS eflag = 1; #else #ifdef CTAGS eflag = 0; #else { char *subname = rindex (progname, '/'); if (subname++ == NULL) subname = progname; eflag = strcmp(subname, "ctags"); } #endif #endif while (ac > 1 && av[1][0] == '-') { for (i=1; av[1][i]; i++) { switch(av[1][i]) { #ifndef VMS /* These options are useful only with ctags, and VMS can't input them, so just omit them. */ case 'B': searchar='?'; eflag = 0; break; case 'F': searchar='/'; eflag = 0; break; #endif case 'a': aflag++; break; case 'e': eflag++; break; case 'f': if (fflag > 0) { fprintf(stderr, "%s: -f flag may only be given once\n", progname); goto usage; } fflag++, ac--; av++; if (ac <= 1 || av[1][0] == '\0') { fprintf(stderr, "%s: -f flag must be followed by a filename\n", progname); goto usage; } outfile = av[1]; goto end_loop; case 'p': pflag++; break; case 't': tflag++; break; #ifndef VMS case 'u': uflag++; eflag = 0; break; #endif case 'w': wflag++; break; case 'v': vflag++; xflag++; eflag = 0; break; case 'x': xflag++; eflag = 0; break; default: goto usage; } } end_loop: ; ac--; av++; } if (ac <= 1) { usage: #ifdef VMS fprintf (stderr, "Usage: %s [-aeptwvx] [-f outfile] file ...\n", progname); #else fprintf (stderr, "Usage: %s [-BFaeptuwvx] [-f outfile] file ...\n", progname); #endif exit(BAD); } if (outfile == 0) { outfile = eflag ? "TAGS" : "tags"; } init(); /* set up boolean "functions" */ initbuffer (&lb); initbuffer (&lb1); /* * loop through files finding functions */ if (eflag) { outf = fopen (outfile, aflag ? "a" : "w"); if (!outf) { fprintf (stderr, "%s: ", progname); perror (outfile); exit (BAD); } } file_num = 1; #ifdef VMS for (ac--, av++; (this_file = gfnames (&ac, &av, &got_err)) != NULL; file_num++) { if (got_err) { error("Can't find file %s\n", this_file); ac--, av++; } else { this_file = massage_name (this_file); #else for (; file_num < ac; file_num++) { this_file = av[file_num]; if (1) { #endif find_entries (this_file); if (eflag) { fprintf (outf, "\f\n%s,%d\n", this_file, total_size_of_entries (head)); put_entries (head); free_tree (head); head = NULL; } } } if (eflag) { fclose (outf); exit (GOOD); } if (xflag) { put_entries(head); exit(GOOD); } if (uflag) { for (i=1; i%s;rm OTAGS", outfile, av[i], outfile); system(cmd); } aflag++; } outf = fopen(outfile, aflag ? "a" : "w"); if (outf == NULL) { fprintf (stderr, "%s: ", outfile); perror(outfile); exit(BAD); } put_entries(head); fclose(outf); #ifndef VMS if (uflag) { sprintf(cmd, "sort %s -o %s", outfile, outfile); system(cmd); } #endif exit(GOOD); } /* * This routine sets up the boolean psuedo-functions which work * by seting boolean flags dependent upon the corresponding character * Every char which is NOT in that string is not a white char. Therefore, * all of the array "_wht" is set to FALSE, and then the elements * subscripted by the chars in "white" are set to TRUE. Thus "_wht" * of a char is TRUE if it is the string "white", else FALSE. */ init() { reg char *sp; reg int i; for (i = 0; i < 0177; i++) { _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; _gd[i] = TRUE; } for (sp = white; *sp; sp++) _wht[*sp] = TRUE; for (sp = endtk; *sp; sp++) _etk[*sp] = TRUE; for (sp = intk; *sp; sp++) _itk[*sp] = TRUE; for (sp = begtk; *sp; sp++) _btk[*sp] = TRUE; for (sp = notgd; *sp; sp++) _gd[*sp] = FALSE; _wht[0] = _wht['\n']; _etk[0] = _etk['\n']; _btk[0] = _btk['\n']; _itk[0] = _itk['\n']; _gd[0] = _gd['\n']; } /* * This routine opens the specified file and calls the function * which finds the function and type definitions. */ find_entries (file) char *file; { char *cp; if ((inf=fopen(file,"r")) == NULL) { fprintf (stderr, "%s: ", progname); perror(file); return; } curfile = savestr(file); cp = rindex(file, '.'); /* .tex, .aux or .bbl implies LaTeX source code */ if (cp && (!strcmp (cp + 1, "tex") || !strcmp (cp + 1, "aux") || !strcmp (cp + 1, "bbl"))) { TEX_funcs(inf); fclose(inf); return; } /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */ if (cp && (!strcmp (cp + 1, "l") || !strcmp (cp + 1, "el") || !strcmp (cp + 1, "lsp") || !strcmp (cp + 1, "lisp") || !strcmp (cp + 1, "cl") || !strcmp (cp + 1, "clisp"))) { L_funcs(inf); fclose(inf); return; } /* .scm or .sm or .scheme implies scheme source code */ if (cp && (!strcmp (cp + 1, "sm") || !strcmp (cp + 1, "scm") || !strcmp (cp + 1, "scheme") || !strcmp (cp + 1, "t") || !strcmp (cp + 1, "sch") || !strcmp (cp + 1, "SM") || !strcmp (cp + 1, "SCM") /* The `SCM' or `scm' prefix with a version number */ || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's') || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'))) { Scheme_funcs(inf); fclose(inf); return; } if (cp && (!strcmp (cp + 1, "C") || !strcmp (cp + 1, "cc") || (pflag && (!strcmp (cp + 1, "c") || !strcmp (cp + 1, "h"))))) { Cplus_funcs(inf); fclose(inf); return; } /* if not a .c or .h or .y file, try fortran */ if (cp && (cp[1] != 'c' && cp[1] != 'h' && cp[1] != 'y') && cp[2] == '\0') { if (PF_funcs(inf) != 0) { fclose(inf); return; } rewind(inf); /* no fortran tags found, try C */ } C_entries(); fclose(inf); } /* Record a tag on the current line. name is the tag name, f is nonzero to use a pattern, zero to use line number instead. */ pfnote (name, f, linestart, linelen, lno, cno) char *name; logical f; /* f == TRUE when function */ char *linestart; int linelen; int lno; long cno; { register char *fp; register NODE *np; char *altname; char tem[51]; if ((np = (NODE *) malloc (sizeof (NODE))) == NULL) { fprintf(stderr, "%s: too many entries to sort\n", progname); put_entries(head); free_tree(head); head = NULL; np = (NODE *) xmalloc(sizeof (NODE)); } /* Change name "main" to M. */ if (!eflag && !xflag && !strcmp(name, "main")) { fp = rindex(curfile, '/'); if (fp == 0) fp = curfile; else fp++; altname = concat ("M", fp, ""); fp = rindex(altname, '.'); if (fp && fp[2] == 0) *fp = 0; name = altname; } np->name = savestr(name); np->file = curfile; np->f = f; np->lno = lno; np->cno = cno; np->left = np->right = 0; if (eflag) { linestart[linelen] = 0; } else if (xflag == 0) { sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart); linestart = tem; } np->pat = savestr (linestart); if (head == NULL) head = np; else add_node(np, head); } free_tree(node) NODE *node; { while (node) { free_tree(node->right); free(node); node = node->left; } } add_node(node, cur_node) NODE *node,*cur_node; { register int dif; dif = strcmp(node->name, cur_node->name); /* If this tag name matches an existing one, then unless -e was given, do not add the node, but maybe print a warning */ if (!eflag && !dif) { if (node->file == cur_node->file) { if (!wflag) { fprintf(stderr,"%s: Duplicate entry in file %s, line %d: %s\n", progname, node->file,node->lno,node->name); fprintf(stderr,"Second entry ignored\n"); } return; } if (!cur_node->been_warned) if (!wflag) fprintf(stderr,"%s: Duplicate entry in files %s and %s: %s (Warning only)\n", progname, node->file, cur_node->file, node->name); cur_node->been_warned = TRUE; return; } /* Actually add the node */ if (dif < 0) { if (cur_node->left != NULL) add_node(node,cur_node->left); else cur_node->left = node; return; } if (cur_node->right != NULL) add_node(node,cur_node->right); else cur_node->right = node; } put_entries(node) reg NODE *node; { reg char *sp; if (node == NULL) return; /* Output subentries that precede this one */ put_entries (node->left); /* Output this entry */ if (eflag) { fprintf (outf, "%s%c%d,%d\n", node->pat, 0177, node->lno, node->cno); } else if (!xflag) { fprintf (outf, "%s\t%s\t", node->name, node->file); if (node->f) { /* a function */ putc (searchar, outf); putc ('^', outf); for (sp = node->pat; *sp; sp++) { if (*sp == '\\' || *sp == searchar) putc ('\\', outf); putc (*sp, outf); } putc (searchar, outf); } else { /* a typedef; text pattern inadequate */ fprintf (outf, "%d", node->lno); } putc ('\n', outf); } else if (vflag) fprintf (stdout, "%s %s %d\n", node->name, node->file, (node->lno+63)/64); else fprintf (stdout, "%-16s%4d %-16s %s\n", node->name, node->lno, node->file, node->pat); /* Output subentries that follow this one */ put_entries (node->right); } /* Return total number of characters that put_entries will output for the nodes in the subtree of the specified node. Works only if eflag is set, but called only in that case. */ total_size_of_entries(node) reg NODE *node; { reg int total = 0; reg long num; if (node == NULL) return 0; /* Count subentries that precede this one */ total = total_size_of_entries (node->left); /* Count subentries that follow this one */ total += total_size_of_entries (node->right); /* Count this entry */ total += strlen (node->pat) + 3; num = node->lno; while (num) { total++; num /= 10; } num = node->cno; if (!num) total++; while (num) { total++; num /= 10; } return total; } /* * This routine finds functions and typedefs in C syntax and adds them * to the list. */ #ifdef VMS long vmslinecharno; #define VMS_SET_LINECHARNO (vmslinecharno = ftell(inf)) #else #define VMS_SET_LINECHARNO #endif #define CNL_SAVE_NUMBER \ { \ VMS_SET_LINECHARNO; \ linecharno = charno; lineno++; \ charno += 1 + readline (&lb, inf); \ lp = lb.buffer; \ } #define CNL \ { \ CNL_SAVE_NUMBER; \ number = 0; \ } C_entries () { register int c; register char *token, *tp, *lp; logical incomm, inquote, inchar, midtoken; int level; char tok[BUFSIZ]; lineno = 0; charno = 0; lp = lb.buffer; *lp = 0; number = 0; gotone = midtoken = inquote = inchar = incomm = FALSE; level = 0; while (!feof (inf)) { c = *lp++; if (c == 0) { CNL; gotone = FALSE; } if (c == '\\') { c = *lp++; if (c == 0) CNL_SAVE_NUMBER; c = ' '; } else if (incomm) { if (c == '*') { while ((c = *lp++) == '*') continue; if (c == 0) CNL; if (c == '/') incomm = FALSE; } } else if (inquote) { /* * Too dumb to know about \" not being magic, but * they usually occur in pairs anyway. */ if (c == '"') inquote = FALSE; continue; } else if (inchar) { if (c == '\'') inchar = FALSE; continue; } else switch (c) { case '"': inquote = TRUE; continue; case '\'': inchar = TRUE; continue; case '/': if (*lp == '*') { lp++; incomm = TRUE; } continue; case '#': if (lp == lb.buffer + 1) number = 1; continue; case '{': if (tydef == tag_ok) { tydef=middle; } level++; continue; case '}': if (lp == lb.buffer + 1) level = 0; /* reset */ else level--; if (!level && tydef==middle) { tydef=end; } continue; } if (!level && !inquote && !incomm && gotone == FALSE) { if (midtoken) { if (endtoken(c)) { int f; char *buf = lb.buffer; int endpos = lp - lb.buffer; char *lp1 = lp; int line = lineno; long linestart = linecharno; #ifdef VMS long vmslinestart = vmslinecharno; #endif int tem = consider_token (&lp1, token, &f, level); lp = lp1; if (tem) { if (linestart != linecharno) { #ifdef VMS getline (vmslinestart); #else getline (linestart); #endif strncpy (tok, token + (lb1.buffer - buf), tp-token+1); tok[tp-token+1] = 0; pfnote(tok, f, lb1.buffer, endpos, line, linestart); } else { strncpy (tok, token, tp-token+1); tok[tp-token+1] = 0; pfnote(tok, f, lb.buffer, endpos, line, linestart); } gotone = f; /* function */ } midtoken = FALSE; token = lp - 1; } else if (intoken(c)) tp++; } else if (begtoken(c)) { token = tp = lp - 1; midtoken = TRUE; } } if (c == ';' && tydef==end) /* clean with typedefs */ tydef=none; } } /* * This routine checks to see if the current token is * at the start of a function, or corresponds to a typedef * It updates the input line * so that the '(' will be * in it when it returns. */ consider_token (lpp, token, f, level) char **lpp, *token; int *f, level; { reg char *lp = *lpp; reg char c; static logical next_token_is_func; logical firsttok; /* T if have seen first token in ()'s */ int bad, win; *f = 1; /* a function */ c = lp[-1]; bad = FALSE; if (!number) { /* space is not allowed in macro defs */ while (iswhite(c)) { c = *lp++; if (c == 0) { if (feof (inf)) break; CNL; } } /* the following tries to make it so that a #define a b(c) */ /* doesn't count as a define of b. */ } else { number++; if (number >= 4 || (number==2 && strncmp (token, "define", 6))) { gotone = TRUE; badone: bad = TRUE; goto ret; } } /* check for the typedef cases */ if (tflag && istoken(token, "typedef", 7)) { tydef=begin; goto badone; } if (tydef==begin && (istoken(token, "struct", 6) || istoken(token, "union", 5) || istoken(token, "enum", 4))) { tydef=tag_ok; goto badone; } if (tydef==tag_ok) { tydef=middle; goto badone; } if (tydef==begin) /* e.g. typedef ->int<- */ { tydef=end; goto badone; } if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */ { tydef=end; } if (tydef==end) { *f = 0; win = 1; goto ret; } /* Detect GNUmacs's function-defining macros. */ if (!number && !strncmp (token, "DEF", 3)) { next_token_is_func = 1; goto badone; } if (next_token_is_func) { next_token_is_func = 0; win = 1; goto ret; } if (c != '(') goto badone; firsttok = FALSE; while ((c = *lp++) != ')') { if (c == 0) { if (feof (inf)) break; CNL; } /* * This line used to confuse ctags: * int (*oldhup)(); * This fixes it. A nonwhite char before the first * token, other than a / (in case of a comment in there) * makes this not a declaration. */ if (begtoken(c) || c=='/') firsttok++; else if (!iswhite(c) && !firsttok) goto badone; } while (iswhite (c = *lp++)) { if (c == 0) { if (feof (inf)) break; CNL; } } win = isgood (c); ret: *lpp = lp - 1; return !bad && win; } getline (atchar) long atchar; { long saveftell = ftell (inf); fseek (inf, atchar, 0); readline (&lb1, inf); fseek (inf, saveftell, 0); } /* C++ parsing */ /* We look for an identifier (other than `if', `while' and `switch') at the outermost parenthesis level, followed by a left parenthesis, followed by a sequence of tokens not including a semicolon, followed by a left brace. This won't find - old-style function definitions - operator function definitions - functions such as int (*foo())() {} Note that it will find functions defined within classes. */ /* Compare a null delimited string with a length delimited string. It's not the same as strncmp: strmemcmp("foobar", "foo", 3) == 1 strncmp("foobar", "foo", 3) == 0 */ static int strmemcmp(s, p, n) char *s, *p; int n; { for (; *s && n > 0; s++, p++, n--) if (*s != *p) return *s - *p; return n ? -1 : (*s ? 1 : 0); } Cplus_funcs () { enum { BOL, /* beginning of line */ START, /* start of a token */ IN_CHAR, IN_CHAR_HAD_BACKSLASH, IN_STRING, IN_STRING_HAD_BACKSLASH, IN_COMMENT, IN_COMMENT_HAD_ASTERISK, HAD_SLASH, IN_EOL_COMMENT, /* in a // comment */ IN_PREPROC, IN_PREPROC_HAD_BACKSLASH, } state = BOL; /* current lexical state */ char *lp; int plevel = 0; /* parenthesis level */ int lineno = 0; int charno = 0; struct { char *name; char *line; int endpos; int lineno; long charno; } entry; /* a possible function definition */ char c = '\0'; entry.name = 0; while (!feof (inf)) { if (c == '\0') { CNL; } c = *lp; if (c != '\0') ++lp; switch (state) { case IN_PREPROC: if (c == '\0') state = BOL; else if (c == '\\') state = IN_PREPROC_HAD_BACKSLASH; break; case IN_PREPROC_HAD_BACKSLASH: if (c != '\\') state = IN_PREPROC; break; case HAD_SLASH: if (c == '/') { state = IN_EOL_COMMENT; break; } if (c == '*') { state = IN_COMMENT; break; } state = START; /* fall through */ case BOL: case START: switch (c) { case '#': if (state == BOL) { while (isspace(*lp)) ++lp; if (strncmp(lp, "define", 6) == 0) { lp += 6; while (isspace(*lp)) lp++; if (isalpha(*lp) || *lp == '_') { char *id_start = lp; do { ++lp; } while (isalnum(*lp) || *lp == '_'); id_start = savenstr(id_start, lp - id_start); pfnote(id_start, 1, lb.buffer, lp - lb.buffer, lineno, linecharno); free(id_start); } } state = IN_PREPROC; } break; case '\0': state = BOL; break; case '/': state = HAD_SLASH; break; case '"': state = IN_STRING; break; case '\'': state = IN_CHAR; break; case '{': if (entry.name) { /* now we know it was a function definition */ pfnote(entry.name, 1, entry.line, entry.endpos, entry.lineno, entry.charno); free(entry.name); free(entry.line); entry.name = entry.line = 0; } break; case ';': if (entry.name) { /* it wasn't a function definition after all */ free(entry.name); free(entry.line); entry.name = entry.line = 0; } break; case '(': plevel += 1; break; case ')': plevel -= 1; break; default: if (isalpha(c) || c == '_') { char *id_start = lp - 1; while (isalnum(*lp) || *lp == '_') lp++; if (!eflag) { char *q = lp; while (isspace(*q)) q++; if (q[0] == ':' && q[1] == ':') { q += 2; while (isspace(*q)) q++; if (isalpha(*q) || *q == '_') { do { ++q; } while (isalnum(*q) || *q == '_'); lp = q; } } } if (entry.name == 0 && plevel == 0 && strmemcmp("while", id_start, lp - id_start) && strmemcmp("if", id_start, lp - id_start) && strmemcmp("switch", id_start, lp - id_start)) { char *p; for (p = lp; isspace(*p); p++) ; if (*p == '(') { /* This is a possible function definition. We won't know for sure until we see left brace, which may be many lines later. So save away the information we need. */ entry.line = savestr(lb.buffer); entry.endpos = lp - lb.buffer; entry.lineno = lineno; entry.charno = linecharno; entry.name = (char *)xmalloc(lp - id_start + 1); strncpy(entry.name, id_start, lp - id_start); entry.name[lp - id_start] = '\0'; } } } break; } if (state == BOL && !isspace(c) && c != '\0') state = START; break; case IN_CHAR: if (c == '\'') state = START; else if (c == '\\') state = IN_CHAR_HAD_BACKSLASH; break; case IN_CHAR_HAD_BACKSLASH: state = IN_CHAR; break; case IN_STRING: if (c == '"') state = START; else if (c == '\\') state = IN_STRING_HAD_BACKSLASH; break; case IN_STRING_HAD_BACKSLASH: state = IN_STRING; break; case IN_COMMENT: if (c == '*') state = IN_COMMENT_HAD_ASTERISK; break; case IN_COMMENT_HAD_ASTERISK: if (c == '/') state = START; else if (c != '*') state = IN_COMMENT; break; case IN_EOL_COMMENT: if (c == '\0') state = BOL; break; default: abort(); } } } /* Fortran parsing */ char *dbp; int pfcnt; PF_funcs(fi) FILE *fi; { lineno = 0; charno = 0; pfcnt = 0; while (!feof (fi)) { lineno++; linecharno = charno; charno += readline (&lb, fi) + 1; dbp = lb.buffer; if (*dbp == '%') dbp++ ; /* Ratfor escape to fortran */ while (isspace(*dbp)) dbp++; if (*dbp == 0) continue; switch (*dbp |' ') { case 'i': if (tail("integer")) takeprec(); break; case 'r': if (tail("real")) takeprec(); break; case 'l': if (tail("logical")) takeprec(); break; case 'c': if (tail("complex") || tail("character")) takeprec(); break; case 'd': if (tail("double")) { while (isspace(*dbp)) dbp++; if (*dbp == 0) continue; if (tail("precision")) break; continue; } break; } while (isspace(*dbp)) dbp++; if (*dbp == 0) continue; switch (*dbp|' ') { case 'f': if (tail("function")) getit(); continue; case 's': if (tail("subroutine")) getit(); continue; case 'p': if (tail("program")) { getit(); continue; } if (tail("procedure")) getit(); continue; } } return (pfcnt); } tail(cp) char *cp; { register int len = 0; while (*cp && (*cp&~' ') == ((*(dbp+len))&~' ')) cp++, len++; if (*cp == 0) { dbp += len; return (1); } return (0); } takeprec() { while (isspace(*dbp)) dbp++; if (*dbp != '*') return; dbp++; while (isspace(*dbp)) dbp++; if (!isdigit(*dbp)) { --dbp; /* force failure */ return; } do dbp++; while (isdigit(*dbp)); } getit() { register char *cp; char c; char nambuf[BUFSIZ]; while (isspace(*dbp)) dbp++; if (*dbp == 0 || !isalpha(*dbp)) return; for (cp = dbp+1; *cp && (isalpha(*cp) || isdigit(*cp)); cp++) continue; c = cp[0]; cp[0] = 0; strcpy(nambuf, dbp); cp[0] = c; pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); pfcnt++; } /* * lisp tag functions * just look for (def or (DEF */ L_funcs (fi) FILE *fi; { lineno = 0; charno = 0; pfcnt = 0; while (!feof (fi)) { lineno++; linecharno = charno; charno += readline (&lb, fi) + 1; dbp = lb.buffer; if (dbp[0] == '(' && (dbp[1] == 'D' || dbp[1] == 'd') && (dbp[2] == 'E' || dbp[2] == 'e') && (dbp[3] == 'F' || dbp[3] == 'f')) { while (!isspace(*dbp)) dbp++; while (isspace(*dbp)) dbp++; L_getit(); } } } L_getit() { register char *cp; char c; char nambuf[BUFSIZ]; if (*dbp == 0) return; for (cp = dbp+1; *cp && *cp != '(' && *cp != ' '; cp++) continue; c = cp[0]; cp[0] = 0; strcpy(nambuf, dbp); cp[0] = c; pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); pfcnt++; } /* * Scheme tag functions * look for (def... xyzzy * look for (def... (xyzzy * look for (def ... ((...(xyzzy .... * look for (set! xyzzy */ static get_scheme (); Scheme_funcs (fi) FILE *fi; { lineno = 0; charno = 0; pfcnt = 0; while (!feof (fi)) { lineno++; linecharno = charno; charno += readline (&lb, fi) + 1; dbp = lb.buffer; if (dbp[0] == '(' && (dbp[1] == 'D' || dbp[1] == 'd') && (dbp[2] == 'E' || dbp[2] == 'e') && (dbp[3] == 'F' || dbp[3] == 'f')) { while (!isspace(*dbp)) dbp++; /* Skip over open parens and white space */ while (*dbp && (isspace(*dbp) || *dbp == '(')) dbp++; get_scheme (); } if (dbp[0] == '(' && (dbp[1] == 'S' || dbp[1] == 's') && (dbp[2] == 'E' || dbp[2] == 'e') && (dbp[3] == 'T' || dbp[3] == 't') && (dbp[4] == '!' || dbp[4] == '!') && (isspace(dbp[5]))) { while (!isspace(*dbp)) dbp++; /* Skip over white space */ while (isspace(*dbp)) dbp++; get_scheme (); } } } static get_scheme() { register char *cp; char c; char nambuf[BUFSIZ]; if (*dbp == 0) return; /* Go till you get to white space or a syntactic break */ for (cp = dbp+1; *cp && *cp != '(' && *cp != ')' && !isspace(*cp); cp++) continue; /* Null terminate the string there. */ c = cp[0]; cp[0] = 0; /* Copy the string */ strcpy(nambuf, dbp); /* Unterminate the string */ cp[0] = c; /* Announce the change */ pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); pfcnt++; } /* Find tags in TeX and LaTeX input files. */ /* TEX_toktab is a table of TeX control sequences that define tags. Each TEX_tabent records one such control sequence. */ struct TEX_tabent { char *name; int len; }; struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */ /* Default set of control sequences to put into TEX_toktab. The value of environment var TEXTAGS is prepended to this. */ static char *TEX_defenv = ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout"; struct TEX_tabent *TEX_decode_env (); static char TEX_esc = '\\'; static char TEX_opgrp = '{'; static char TEX_clgrp = '}'; /* * TeX/LaTeX scanning loop. */ TEX_funcs (fi) FILE *fi; { char *lasthit; lineno = 0; charno = 0; pfcnt = 0; /* Select either \ or ! as escape character. */ TEX_mode (fi); /* Initialize token table once from environment. */ if (!TEX_toktab) TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv); while (!feof (fi)) { lineno++; linecharno = charno; charno += readline (&lb, fi) + 1; dbp = lb.buffer; lasthit = dbp; while (!feof (fi)) { /* Scan each line in file */ lineno++; linecharno = charno; charno += readline (&lb, fi) + 1; dbp = lb.buffer; lasthit = dbp; while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */ { register int i; if (! *(++dbp)) break; linecharno += dbp - lasthit; lasthit = dbp; i = TEX_Token (lasthit); if (0 <= i) { TEX_getit (lasthit, TEX_toktab[i].len); break; /* We only save a line once */ } } } } } #define TEX_LESC '\\' #define TEX_SESC '!' /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */ /* chars accordingly. */ TEX_mode (f) FILE *f; { int c; while ((c = getc (f)) != EOF) if (c == TEX_LESC || c == TEX_SESC) break; if (c == TEX_LESC) { TEX_esc = TEX_LESC; TEX_opgrp = '{'; TEX_clgrp = '}'; } else { TEX_esc = TEX_SESC; TEX_opgrp = '<'; TEX_clgrp = '>'; } rewind (f); } /* Read environment and prepend it to the default string. */ /* Build token table. */ struct TEX_tabent * TEX_decode_env (evarname, defenv) char *evarname; char *defenv; { register char *env, *p; extern char *savenstr (), *index (); struct TEX_tabent *tab; int size, i; /* Append deafult string to environment. */ env = (char *) getenv (evarname); if (!env) env = defenv; else env = concat (env, defenv, ""); /* Allocate a token table */ for (size = 1, p=env; p;) if ((p = index (p, ':')) && *(++p)) size++; tab = (struct TEX_tabent *) xmalloc (size * sizeof (struct TEX_tabent)); /* Unpack environment string into token table. Be careful about */ /* zero-length strings (leading ':', "::" and trailing ':') */ for (i = 0; *env;) { p = index (env, ':'); if (!p) /* End of environment string. */ p = env + strlen (env); if (p - env > 0) { /* Only non-zero strings. */ tab[i].name = savenstr (env, p - env); tab[i].len = strlen (tab[i].name); i++; } if (*p) env = p + 1; else { tab[i].name = NULL; /* Mark end of table. */ tab[i].len = 0; break; } } return tab; } /* Record a tag defined by a TeX command of length LEN and starting at NAME. The name being defined actually starts at (NAME + LEN + 1). But we seem to include the TeX command in the tag name. */ TEX_getit (name, len) char *name; int len; { char *p = name + len; char nambuf[BUFSIZ]; if (*name == 0) return; /* Let tag name extend to next group close (or end of line) */ while (*p && *p != TEX_clgrp) p++; strncpy (nambuf, name, p - name); nambuf[p - name] = 0; pfnote (nambuf, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno); pfcnt++; } /* If the text at CP matches one of the tag-defining TeX command names, return the index of that command in TEX_toktab. Otherwise return -1. */ /* Keep the capital `T' in `Token' for dumb truncating compilers (this distinguishes it from `TEX_toktab' */ TEX_Token (cp) char *cp; { int i; for (i = 0; TEX_toktab[i].len > 0; i++) if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0) return i; return -1; } /* Initialize a linebuffer for use */ void initbuffer (linebuffer) struct linebuffer *linebuffer; { linebuffer->size = 200; linebuffer->buffer = (char *) xmalloc (200); } /* Read a line of text from `stream' into `linebuffer'. Return the length of the line. */ long readline (linebuffer, stream) struct linebuffer *linebuffer; register FILE *stream; { char *buffer = linebuffer->buffer; register char *p = linebuffer->buffer; register char *pend = p + linebuffer->size; while (1) { int c = getc (stream); if (p == pend) { buffer = (char *) xrealloc (buffer, linebuffer->size *= 2); p += buffer - linebuffer->buffer; pend = buffer + linebuffer->size; linebuffer->buffer = buffer; } if (c < 0 || c == '\n') { *p = 0; break; } *p++ = c; } return p - buffer; } char * savestr(cp) char *cp; { return savenstr (cp, strlen (cp)); } char * savenstr(cp, len) char *cp; int len; { register char *dp; dp = (char *) xmalloc (len + 1); strncpy (dp, cp, len); dp[len] = '\0'; return dp; } /* * Return the ptr in sp at which the character c last * appears; NULL if not found * * Identical to v7 rindex, included for portability. */ char * rindex(sp, c) register char *sp, c; { register char *r; r = NULL; do { if (*sp == c) r = sp; } while (*sp++); return(r); } /* * Return the ptr in sp at which the character c first * appears; NULL if not found * * Identical to v7 index, included for portability. */ char * index(sp, c) register char *sp, c; { do { if (*sp == c) return (sp); } while (*sp++); return (NULL); } /* Print error message and exit. */ fatal (s1, s2) char *s1, *s2; { error (s1, s2); exit (BAD); } /* Print error message. `s1' is printf control string, `s2' is arg for it. */ error (s1, s2) char *s1, *s2; { fprintf (stderr, "%s: ", progname); fprintf (stderr, s1, s2); fprintf (stderr, "\n"); } /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ char * concat (s1, s2, s3) char *s1, *s2, *s3; { int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); char *result = (char *) xmalloc (len1 + len2 + len3 + 1); strcpy (result, s1); strcpy (result + len1, s2); strcpy (result + len1 + len2, s3); *(result + len1 + len2 + len3) = 0; return result; } /* Like malloc but get fatal error if memory is exhausted. */ char * xmalloc (size) int size; { char *result = malloc (size); if (!result) fatal ("virtual memory exhausted", 0); return result; } char * xrealloc (ptr, size) char *ptr; int size; { char *result = realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); return result; } trcpy (result + len1, s2); strcpy (result + len1 + len2, s3); *(result + len1 + len2 + len3) = 0; return result; } /* Like malloc but get fatal error if memory is exhausted. */ char * xmalloc (size) int size; { char *result = malloc (size); if (!result) fatal ("virtual memory exhausted", 0); return result; } char * xrealloc (ptr, size) char *ptr; int silibg++/etc/g++dep 755 473 0 2651 4677700013 6704 #! /bin/sh # This utility is a lightly editted version of the freed Berkeley # script `mkdep'. The current script is intended to work for GNU G++. # Here is the original BSD header: # @(#)mkdep.sh 1.7 (Berkeley) 10/13/87 # # PATH=/bin:/usr/bin:/usr/ucb:/usr/gnu:/usr/gnu/bin export PATH if [ $# = 0 ] ; then echo 'usage: g++dep [-p] [-f makefile] [flags] file ...' exit 1 fi MAKE=Makefile # default makefile name is "Makefile" case $1 in # -f allows you to select a makefile name -f) MAKE=$2 shift; shift ;; # the -p flag produces "program: program.c" style dependencies # so .o's don't get produced -p) SED='-e s;\.o;;' shift ;; esac if [ ! -w $MAKE ]; then echo "g++dep: no writeable file \"$MAKE\"" exit 1 fi TMP=/tmp/g++dep$$ trap 'rm -f $TMP ; exit 1' 1 2 3 13 15 cp $MAKE ${MAKE}.bak sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP cat << _EOF_ >> $TMP # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. _EOF_ g++ -M $* | /bin/sed -e "s; \./; ;g" $SED | \ awk ' { \ if ($1 != prev) { \ if (rec != "") \ print rec; rec = $0; prev = $1; \ } \ else { \ if (length(rec $2) > 78) { \ print rec; rec = $0; \ } else \ rec = rec " " $2 \ } \ } \ END { \ print rec \ } ' >> $TMP cat << _EOF_ >> $TMP # IF YOU PUT ANYTHING HERE IT WILL GO AWAY _EOF_ # copy to preserve permissions cp $TMP $MAKE rm -f ${MAKE}.bak $TMP exit 0 it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. _EOF_ g++ -M $* | /bin/selibg++/etc/ADT-examples/Patmain.cc 600 473 0 2033 4677700013 12017 // Tests the Patricia tree #include #include "Patricia.h" double start_timer (void); double return_elapsed_time (double); const int MAX_KEY_LEN = 1000; main (int argc, char *argv[]) { if (argc != 3) { cerr << "usage: " << argv [0] << " file1 file2\n"; return 1; } else { if (!freopen (argv [1], "r", stdin)) { perror (argv [0]); return 1; } Patricia_Trie trie; char key [MAX_KEY_LEN]; while (gets (key)) trie.insert (key, 0); fclose (stdin); if (! freopen (argv [2], "r", stdin)) { perror (argv [0]); return 1; } start_timer (); while (gets (key)) { Trie_Record *t = trie.find (key); cout << key << ": " << (! strcmp (key, t->get_key ()) ? "is found!\n" : "is not found!\n"); } double Elapsed_Time = return_elapsed_time (0.0); cout << "Time = " << Elapsed_Time << "\n"; fclose (stdin); return 0; } } fclose (stdin); if (! freopen (argv [2], "r", stdin)) { perror (argv [0]); return 1; } start_timer (); while (gets (key)) { Trie_Record *t = trie.find (key); cout << key << ": " << (! strcmp (key, t->get_key ()) ? "is found!\n" : "is not found!\n"); } double Elapsed_Time = return_elapsed_time (0.0); cout << "Time = " << Elapsed_Time << "\n"; fclose (stdin); libg++/etc/ADT-examples/Patricia.cc 600 473 0 14212 4677700013 12204 /* Implements the PATRICIA trie abstraction. */ #include #include "Patricia.h" Trie_Node::Trie_Node (char *k, int len, CONTENTS new_contents, int b): branch_bit (b) { trie_rec.set_contents (new_contents); /* Dynamically compute the length, if it's not given */ if (!len) len = strlen (k) + 1; trie_rec.set_key (strcpy (new char[len], k)); } /* Recursively free tree memory via modified post-order traversal */ void Patricia_Trie::dispose_trie (Trie_Node *root) { if (root->left->branch_bit <= root->branch_bit && root->right->branch_bit <= root->branch_bit) ; /* do nothing! */ else if (root->left->branch_bit <= root->branch_bit) dispose_trie (root->right); else if (root->right->branch_bit <= root->branch_bit) dispose_trie (root->left); else { dispose_trie (root->left); dispose_trie (root->right); } delete root; } /* Initializes Patricia_Trie, using dummy header. */ Patricia_Trie::Patricia_Trie (void) { root = new Trie_Node; root->left = root; root->right = root; } /* Frees all dynamic memory in Patricia Trie */ Patricia_Trie::~Patricia_Trie (void) { dispose_trie (root->left); delete root; } /* Attempts to locate the record associated with Key. The basic algorithm is abstractly similar to Sedgewick's description in his Algorithm's book. However, I've modified things to speed up the Bit comparisons greatly, as well as to run the Branch_Bit index from 0..whatever, since this allows arbitrarily large keys (For some strange reason Sedgewick goes from some predefined limit, Max_Branch_Bit, *downto* 0!!). Most of the contortions below help manage a Bit cache, which reduces the total amount of work required to test the next Branch_Bit. Empirical tests revealed that this was main bottleneck in the Find routine. To make the algorithm work I needed to have the first Bit in the first word always be 0. Therefore, I've ordered the bits from high-order Bit to low-order Bit (e.g., 8 .. 1), running from word 0 to word K. This fits intuitively with how you might draw the bits onn paper, but *not* with how it would work if you programmed it in the normal way (i.e., running from bit 1 to 8, from word 0 to K). At any rate, that's what the BIT macro is for, it normalizes my abstract concept of bit-order with the actual bit-order. */ Trie_Record * Patricia_Trie::find (char *key) { Trie_Node *parent; Trie_Node *cur = root->left; /* Root is *always* a dummy node, skip it */ char *block = key; /* Pointer to Current Block of Bits */ int lower = 0; do { parent = cur; int bit = cur->branch_bit - lower; /* Oh well, time to refill the Bit cache! This loop gets executed infrequently, in general */ if (bit >= WORD_BITS) while (lower + WORD_BITS <= cur->branch_bit) { lower += WORD_BITS; ++block; bit -= WORD_BITS; } cur = (is_bit_set (*block, get_bit (bit)) ? cur->right : cur->left); } while (parent->branch_bit < cur->branch_bit); return &cur->trie_rec; /* Let calling routine worry whether Keys matched! */ } /* Inserts a new KEY and its associated CONTENTS into the trie. */ void Patricia_Trie::insert (char *key, CONTENTS contents, int key_len) { Trie_Node *parent; Trie_Node *cur = root; char *block = key; int lower = 0; /* This loop is essentially the same as in the Find routine. */ do { parent = cur; int bit = cur->branch_bit - lower; if (bit >= WORD_BITS) while (lower + WORD_BITS <= cur->branch_bit) { lower += WORD_BITS; ++block; bit -= WORD_BITS; } cur = (is_bit_set (*block, get_bit (bit)) ? cur->right : cur->left); } while (parent->branch_bit < cur->branch_bit); /* Exclude duplicates */ if (strcmp (key, cur->trie_rec.get_key ())) { char *key_block = key; char *cur_block = cur->trie_rec.get_key (); /* Find the first word where Bits differ, skip common prefixes. */ for (int first_bit_diff = 0; *cur_block == *key_block; first_bit_diff += WORD_BITS) cur_block++, key_block++; /* Now, find location of that Bit, xor does us a favor here. */ for (int bit = *cur_block ^ *key_block; !(bit & POW2 (HI_WORD)); bit <<= 1) first_bit_diff++; /* *Not* adding at a leaf node */ if (parent->branch_bit > first_bit_diff) { /* This is almost identical to the original Find above, however, we are */ /* guaranteed to end up at an internal node, rather than a leaf. */ for (cur = root, lower = 0, cur_block = key; ;) { parent = cur; int bit = cur->branch_bit - lower; if (bit >= WORD_BITS) while (lower + WORD_BITS <= cur->branch_bit) { lower += WORD_BITS; ++cur_block; bit -= WORD_BITS; } cur = (is_bit_set (*cur_block, get_bit (bit)) ? cur->right : cur->left); if (cur->branch_bit >= first_bit_diff) break; } } Trie_Node *t = new Trie_Node (key, key_len, contents, first_bit_diff); /* Key_Block was saved from above, this avoids some costly recomputation. */ if (is_bit_set (*key_block, get_bit (first_bit_diff & BIT_MASK))) t->left = cur, t->right = t; else t->left = t, t->right = cur; /* Determine whether the new node goes to the left or right of its parent */ block = key + (parent->branch_bit >> WORD_SHIFT); (is_bit_set (*block, get_bit (parent->branch_bit & BIT_MASK)) ? parent->right : parent->left) = t; } } /* Key_Block was saved from above, this avoids some costly recomputation. */ if (is_bit_set (*key_block, get_bit (first_bit_diff & BIT_MASK))) t->left = cur, t->right = t; else t->left = t, t->right = cur; /* Determine whether the new node goes to the left or right of its parent */ block = key + (parent->branch_bit libg++/etc/ADT-examples/Patricia.h 600 473 0 4471 4677700013 12034 /* Implements the PATRICIA Trie ADT. PATRICIA stands for ``Practical Algorithm to Retrieve Information Coded in Alphanumeric.'' PATRICIA was developed by D.R. Morrison. The current implementation is based upon Robert Sedgewick's description in his Algorithms book. Includes operations for * Initialization * Insertion * Retrieval */ /* This could change, depending on what client wants */ typedef void *CONTENTS; /* Record structure that *must* be visible to clients. */ class Trie_Record { private: char *key; /* Only works safely and easily for char *'s */ CONTENTS contents; /* Pointer to record Contents referenced by Key */ public: char *get_key (void) { return key; } CONTENTS get_contents (void) { return contents; } void set_key (char *k) { key = k; } void set_contents (CONTENTS c) { contents = c; } }; class Patricia_Trie { private: const int HI_WORD = 7; /* Hi-order bit, starting count from 0 */ const int BIT_MASK = 07; /* WORD_SHIFT low-order bits enabled */ const int WORD_BITS = 8; /* Number of Bits in a Block */ const int WORD_SHIFT = 3; /* i.e. lg (WORD_BITS) */ /* Nested class definition, should be invisible to clients with new C++ scoping rules... */ struct Trie_Node { Trie_Record trie_rec; /* Stores data in the Trie */ int branch_bit; /* Stores index of next Bit to compare */ Trie_Node *left; /* Pointer to left child. */ Trie_Node *right; /* Pointer to right child. */ Trie_Node (char *k = "", int len = 0, CONTENTS new_contents = 0, int b = 0); }; /* Root for the entire Patricia tree, (actually a dummy header!). */ Trie_Node *root; /* Recursively free tree memory via modified post-order traversal. */ void dispose_trie (Trie_Node *root); /* Normalizes the ith Bit representation */ inline int get_bit (int i) { return HI_WORD - i; } /* Returns 1 if bit is set. */ inline int is_bit_set (int block, int shift) { return (block & (1 << shift)) != 0; } /* Return the ith power of 2. */ inline int POW2 (int i) { return 1 << i; } public: Patricia_Trie (void); ~Patricia_Trie (void); Trie_Record *find (char *key); void insert (char *key, CONTENTS contents, int key_len = 0); }; raversal. */ void dispose_trie (Trie_Node *root); /* Normalizes the ith Bit representation */ inline int get_bit (int i) { return HI_WORD - i; } /* Returns 1 if bit is set. */ inline int libg++/etc/ADT-examples/tsort.cc 644 473 0 20224 4677700014 11634 /* Date: Sun, 18 Sep 88 15:57:31 -0700 From: "Douglas C. Schmidt" The following tool performs topological sorting in O(n + m) average-time (n == # of vertices, m == # of edges). If you happen to have Andrew Koenig's Summer USENIX '88 article on Associative Arrays in C++ it is interesting to compare his solution to mine. Basically, my version, which uses hashing as opposed to his AVL trees, should be *much* faster on the average (it would be interesting to compare the two). In fact, if you test the code below against the standard UNIX tsort routine, you should be *amazed* at how much faster it is (several orders of magnitude on large input files)! */ #include #include /* Forward class decls. */ class Vertex_Node; class Assoc_Array; class Assoc_Iter; /* Defines and implements the adjacency list abstraction that contains the list of vertices that are incident to given vertex. Note that we store Vertex_Node pointers here, rather than vertex *Names*. This allows us to find a particular vertex in the Hash_Table in O(1) time, without having to perform the usual hash lookup (compare this with Andrew Koenig's implementation from the Summer USENIX '88 proceedings!) */ class Adjacency_Node { private: Vertex_Node *item_ptr; Adjacency_Node *next_ptr; public: /* The constructor simply orders the adjacency list as a stack. */ Adjacency_Node (Vertex_Node *new_item, Adjacency_Node *head): item_ptr (new_item), next_ptr (head) {} Vertex_Node *item (void) { return item_ptr; } Adjacency_Node *next (void) { return next_ptr; } }; /* The Hash_Table is composed of these Vertex_Nodes. Each Vertex_Node contains an adjacency list of successor nodes, and an In_Degree count. Each operation is extremely concise and self-explanatory, with the exception of the overloaded ``+='' operator, which essentially means ``Add the successor node to the successor list (OK, so this is an abuse of overloading!) */ class Vertex_Node { friend class Assoc_Array; friend class Assoc_Iter; private: int in_degree; String name; Adjacency_Node *succ_list; Vertex_Node *next; public: Vertex_Node (String &item, Vertex_Node *n = 0): in_degree (0), name (item), next (n), succ_list (0) {} int in_degree_count (void) { return in_degree; } Adjacency_Node *get_succ_list (void) { return succ_list; } Vertex_Node& operator++ (void) { in_degree++; return *this; } int operator-- (void) { return --in_degree; } Vertex_Node& operator+= (Vertex_Node& succ_node) { succ_list = new Adjacency_Node (&succ_node,succ_list); return *this; } String &item (void) { return name; } friend ostream& operator << (ostream& stream,Vertex_Node& output) { return stream << output.in_degree; } }; /* Here's the main data structure. It is simply a Hash_Table of Vertex_Nodes. I make use of hashpjw from the libg++ builtin library. Nothing too tricky here.... I overload the [] operator to provide the classic ``associative array'' touch. */ class Assoc_Array { friend class Vertex_Node *Assoc_Iter::operator ()(void); private: int total_size; int current_size; Vertex_Node **hash_table; public: Assoc_Array (int size): total_size (size), current_size (0) { hash_table = new Vertex_Node *[size]; bzero (hash_table, size * sizeof *hash_table); } Vertex_Node& operator[](String index) { int location = hashpjw (index) % total_size; Vertex_Node *head = hash_table[location]; if (!head) { current_size++; return *(hash_table[location] = new Vertex_Node (index)); } else { for ( ; head; head = head->next) if (head->name == index) return *head; current_size++; return *(hash_table[location] = new Vertex_Node (index, hash_table[location])); } } int array_size (void) { return current_size; } int max_size (void) { return total_size; } }; /* This is a neat class, which implements an iterator for the Hash_Table used for the associative array. It would be faster to search the table directly, without using an iterator, but this is a neat feature of C++ that fits too nicely into the overall abstraction to pass up! */ class Assoc_Iter { private: Vertex_Node *curr; Assoc_Array *assoc; int curr_table_pos; public: Assoc_Iter (Assoc_Array& array,int items): assoc (&array), curr (0), curr_table_pos (items - 1) {} Vertex_Node *operator() (void) { if (curr_table_pos <= 0) /* we're at the end of the table, quit. */ return 0; else if (!curr) { /* need to find a new bucket list to search. */ while (curr_table_pos >= 0 && !assoc->hash_table[curr_table_pos]) curr_table_pos--; if (curr_table_pos < 0) return 0; else curr = assoc->hash_table[curr_table_pos]; } Vertex_Node *temp = curr; if (!(curr = curr->next)) /* try to update curr for next call. */ curr_table_pos--; return temp; } }; /* This is a very simple stack abstraction. Doesn't perform error checking. */ class Node_Stack { private: int top; int max_node_stack_size; Vertex_Node **node_stack_items; public: Node_Stack (int size): top (size), max_node_stack_size (size) { node_stack_items = new Vertex_Node *[size]; } int empty () { return top >= max_node_stack_size; } void push (Vertex_Node *item) { node_stack_items[--top] = item; } Vertex_Node *pop (void) { return node_stack_items[top++]; } }; const int DEFAULT_SIZE = 200; const int BUF_SIZE = 200; main (int argc, char **argv) { Assoc_Array assoc_array (argc > 1 ? atoi (argv[1]) : DEFAULT_SIZE); String prev; String succ; /* The use of ``+='' below is rather obscure. It simply means ``prepend the address of A[Succ] to the adjacency list of A[Prev]. See the comment in the member definition for class Vertex_Node. Note that the ++ operator has also been overloaded. This allows concise, extremely efficient mechanism to enter the Prev and Succ items into the associative array. */ while (cin >> prev >> succ) if (prev == succ) /* Just record existence of identical tokens. */ assoc_array[prev]; else assoc_array[prev] += ++assoc_array[succ]; Assoc_Iter next (assoc_array, assoc_array.max_size ()); Node_Stack stack (assoc_array.array_size ()); Vertex_Node *node_ptr; /* Iterate through all the items in the associative array, performing the typical topological sort trick of pushing all ``sources'' onto a stack. This gives us an order of magnitude win over the standard UNIX tsort routine, which has quadratic average time complexity (in the number of verticies!!!!). */ while (node_ptr = next ()) if (node_ptr->in_degree_count () == 0) stack.push (node_ptr); /* The following code is straight-forward, but the one line with the expression --(*List->Item ()) == 0 is rather cryptic. It is simply dereferencing a pointer to a Vertex_Node, and then passing this by reference to the overloaded -- operator from the Vertex_Node class (yes, it *is* easy to abuse this technique!). */ for (int items = 0; !stack.empty (); items++) { node_ptr = stack.pop (); cout << node_ptr->item () << "\n"; for (Adjacency_Node *list = node_ptr->get_succ_list (); list; list = list->next ()) if (--*list->item () == 0) stack.push (list->item ()); } if (items != assoc_array.array_size ()) { cerr << argv[0] << ": error, directed graph has a cycle!\n"; return 1; } else return 0; } que!). */ for (int items = 0; !stack.empty (); items++) { node_ptr = stack.pop (); cout << node_ptr->item () << "\n"; for (Adjacency_Node *list = node_ptr->get_succ_list (); list; list = list->next ()) if (--*list->item () == 0) stack.push (list->item ()); } if (items !libg++/etc/ADT-examples/search.cc 600 473 0 13256 4677700014 11725 // From: "Douglas C. Schmidt" // Date: Sat, 29 Oct 88 14:11:51 -0700 #include /**********************************************************************/ /**********************************************************************/ typedef int ITEM_TYPE; class Additive_Search { // Implements the binary search variation described on pages 138 and 139 // of Tim Standish's ``Data Structure Techniques'' textbook. The big // win here is that this version uses no division (or right shift), // only addition, so it runs faster on most computers. private: ITEM_TYPE *Vector_Buffer; // Hold's copy of the initialized search structure int Vector_Length; // Length of the user's input static int Tree_Height; // Height of the implicit binary search tree static ITEM_TYPE *Temp; // Temporary storage during initialization void Fill_Buffer (int h, int i); // Transforms sorted array into special // representation that supports the // additive binary search technique public: Additive_Search (ITEM_TYPE *Array, int Len); int Is_Member (ITEM_TYPE K); ~Additive_Search (void); }; /**********************************************************************/ void Additive_Search::Fill_Buffer (int Hgt, int Index) { // Uses a very concise recursive routine to initialize the Vector_Buffer from // the original sorted array (which must have been sorted, or else this // *won't* work)! This magic sequence of statements transforms the original sorted // array into an new array representing the level order traversal of a complete // binary search tree. See Standish, page 138 for details... if ((Hgt <= Tree_Height) && (Index < Vector_Length)) { Fill_Buffer (Hgt + 1, (Index + Index) + 1); Vector_Buffer [Index] = *Temp++; Fill_Buffer (Hgt + 1, (Index + Index) + 2); } } /**********************************************************************/ Additive_Search::Additive_Search (ITEM_TYPE *Array, int Len) { Tree_Height = lg (Len); Vector_Length = Len; Temp = Array; Vector_Buffer = new ITEM_TYPE [Len]; Fill_Buffer (0, 0); // Tree_Height and Index both start off at 0 } /**********************************************************************/ int Additive_Search::Is_Member (ITEM_TYPE K) { // Performs the additive binary search upon the initialized Vector_Buffer. // Note that we perform no division or multiplication in this search. // Such omissions generally yield faster running times on most machines. register int i = 0; while (i < Vector_Length) { register int Cmp = (Vector_Buffer [i] - K); if (Cmp == 0) return 1; else { i += i + 1; if (Cmp < 0) i++; } } return 0; } /**********************************************************************/ Additive_Search::~Additive_Search (void) { delete Vector_Buffer; } /**********************************************************************/ /**********************************************************************/ class Binary_Search { // Performs the typical binary search algorithm. For comparison purposes only. #define COPY(DEST,SRC,NB) {register typeof(DEST) a = (DEST), b = (SRC);\ register int i, j = (NB);\ for (i = (j & 07)+1; --i;) *a++ = *b++;\ for (i = (j>>3)+1; --i>0;) {\ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++;\ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++;\ }} private: ITEM_TYPE *Vector_Buffer; int Vector_Length; public: Binary_Search (ITEM_TYPE *Array, int Len): Vector_Length (Len) { Vector_Buffer = new ITEM_TYPE [Len]; COPY (Vector_Buffer, Array, Len); // The infamous Duff's Device! } int Is_Member (ITEM_TYPE K) { // Yawn, this looks familiar register int hi; register int lo; for (lo = 0, hi = Vector_Length - 1; lo <= hi ;) { register int mid = (lo + hi) >> 1; if (Vector_Buffer [mid] == K) return 1; else if (Vector_Buffer [mid] < K) lo = mid + 1; else hi = mid - 1; } return 0; } ~Binary_Search (void) { delete Vector_Buffer; } }; /**********************************************************************/ static int Cmp (void *A, void *B) { // Too bad we lack lambdas! return (*(ITEM_TYPE*)A < *(ITEM_TYPE*)B)? -1 : ((*(ITEM_TYPE*)A == *(ITEM_TYPE*)B) ? 0 : 1); } /**********************************************************************/ double return_elapsed_time (double); double start_timer (void); void Gen_Rand (ITEM_TYPE Buf[], int Size); int main (int, char *argv[]) { int Size = atoi (argv [1]); ITEM_TYPE Buf [Size]; Gen_Rand (Buf, Size); qsort ((void *) Buf, Size, sizeof (ITEM_TYPE), Cmp); Additive_Search Foo (Buf, Size); Binary_Search Bar (Buf, Size); start_timer (); for (int i = 0; i < Size ; i++) if (! Bar.Is_Member (Buf [i])) cout << "bad news, buf [" << i << "] = " << Buf [i] << "!\n"; double Elapsed_Time = return_elapsed_time (0.0); cout << "Binary Time = " << Elapsed_Time << "\n"; start_timer (); for (i = 0; i < Size ; i++) if (! Foo.Is_Member (Buf [i])) cout << "bad news, buf [" << i << "] = " << Buf [i] << "!\n"; Elapsed_Time = return_elapsed_time (0.0); cout << "Additive Time = " << Elapsed_Time << "\n"; return 0; } void Gen_Rand (ITEM_TYPE Buf[], int Size) { // Generates some random numbers srandom (getpid ()); for (int i = 0; i < Size; i++) Buf [i] = ITEM_TYPE (random ()); } 0.0); cout << "Binary Time = " << Elapsed_Time << "\n"; start_timer (); for (i = 0; i < Size ; i++) if (! Foo.Is_Member (Buf [i])) cout << "bad news, buf [" << i << "] = " << Buf [i] << "!\n"; Elapsed_Time = return_elapsed_time (0.0); cout << "Additive Time = " << Elapsed_Time << "\n"; return 0; } void Gelibg++/etc/ADT-examples/kmp.cc 600 473 0 25632 4677700014 11250 //From: "Douglas C. Schmidt" //Date: Fri, 28 Jul 89 11:47:11 -0700 /* Nifty little program that illustrates an implementation of the Knuth, Morris, Pratt string matching algorithm. This program has a user interface similar to fgrep, i.e., when you provide it with a fixed pattern it prints out all the lines from the standard input (or one user-specified input file) that contain at least one substring that matches the provided pattern. Relevant options are: -i: Ignore case when performing comparisons. -n: Print out lines numbers along with the matching lines. -v: Print out lines that *don't* match the pattern. The code below is extensively commented. If these comments distract you, run the code through g++ -E first ;-). */ #include #include #include /* This array is designed for mapping upper and lower case letter together for a case independent comparison. The mappings are based upon the ASCII character sequences. */ char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; /* The list of available program options. */ enum options { DEBUG, FOLD_CASE, LINE_NUMBERS, INVERSE, OPTION_SIZE }; /* Vector storing the enabled options (all initially disabled). */ char option[OPTION_SIZE]; /* Data and function members necessary to implement the KMP algorithm. */ class kmp { private: #ifdef GNUG const int RESET_PATTERN_FLAG = -1; #else #define RESET_PATTERN_FLAG -1 #endif int *fail_trans_table; /* Stores the generated nfa used when matching. */ char *pattern; /* Stores the user-supplied pattern. */ int pattern_len; /* Pattern length. */ void print_fail_trans_table (void); public: kmp (char *pattern, int pattern_len, int debug = 0); ~kmp () { delete fail_trans_table; } int operator ()(char *text, int text_len); }; /* Provide a debugging dump of the failure function. Nothing fancy... */ void kmp::print_fail_trans_table (void) { int i; for (i = 0; i < pattern_len; i++) printf ("%3d,", i); putchar ('\n'); for (i = 0; i < pattern_len; i++) printf ("%3d,", fail_trans_table [i]); putchar ('\n'); } /* This constructor builds the transition table that encodes the failure function automaton. The table stores the PATTERN index we go to in the event of a mismatch with the input text string. This generation process runs in time linear to the pattern size. The terms SUFFIX and PREFIX used below are defined in terms of each other. That is, at each state of the failure function we seek to determine the largest pattern prefix that matches with the largest suffix in the actual input text. This information informs us how far we can legitimately shift the pattern to the right when a mismatch occurs during the string matching process. Stated more formally, this means that for all i (0 <= i <= (PATTERN_LEN - 1)) FAIL_TRANS_TABLE (i) is the largest j < i, such that PATTERN[1..j - 1] is a suffix of PATTERN[1..i - 1] and PATTERN[i] != PATTERN[j]. */ kmp::kmp (char *pat, int len, int debug): pattern (pat), fail_trans_table (new int[len]), pattern_len (len) { /* Points 1 beyond the rightmost potential *suffix* in the pattern (which is actually simulating the behavior of an actual input text string. */ int suffix_end = 0; /* Points 1 beyond the rightmost potential *prefix* in the pattern. */ int prefix_end = fail_trans_table[suffix_end] = RESET_PATTERN_FLAG; do { /* This WHILE loop uses the precomputed failure function to look further left into the pattern trying to find an index location where the pattern prefix matches the pattern suffix. However, if/when we locate the RESET_PATTERN_FLAG this means that we can just skip ahead to the next character in the input text. */ while (prefix_end != RESET_PATTERN_FLAG && pattern[suffix_end] != pattern[prefix_end]) prefix_end = fail_trans_table[prefix_end]; /* Once SUFFIX_END and PREFIX_END are pre-incremented below we know that the first PREFIX_END characters of PATTERN match the characters in positions PATTERN[SUFFIX_END - PREFIX_END .. SUFFIX_END - 1], i.e., the last PREFIX_END characters in the rightmost part of the first SUFFIX_END - 1 characters in PATTERN. If the character at location PATTERN[SUFFIX_END] matches that at PATTERN[PREFIX_END] it is silly to have the failure transition jump to that pattern location (since it would immediately fail to match, of course!). Instead, in that case we just ``borrow'' the previously computed transition stored at FAIL_TRANS_TABLE[PREFIX_END] and use it. */ if (pattern[++suffix_end] == pattern[++prefix_end]) fail_trans_table[suffix_end] = fail_trans_table[prefix_end]; else fail_trans_table[suffix_end] = prefix_end; } /* Adding the extra 1 here is necessary since C strings are indexed from 0 to pattern_len - 1... */ while (suffix_end + 1 < pattern_len); if (debug) print_fail_trans_table (); } /* Actually perform the KMP matching algorithm using the generated determinisitic pattern matching match encoded in the failure transition table. This version is optimized on the assumption that there will be more characters in the text input that *don't* match the pattern than ones that do match it. Therefore, we make a special effort to keep looping through the failure function as long as the text and pattern don't match. */ int kmp::operator ()(char *text, int text_len) { int suffix_end = RESET_PATTERN_FLAG; int prefix_end = RESET_PATTERN_FLAG; /* If TEXT length is shorted than PATTERN we'll bail out now... */ if (text_len < pattern_len) return 0; /* Split the following two cases so that we don't pay any unnecessary overhead when case folding is not required. */ if (option[FOLD_CASE]) /* Note how this main loop is almost identical with the `failure transition table building' algorithm used above. */ do { /* Ignore case when matching and keep applying the failure function until we get a match or are forced to restart the pattern (starting with the *following* input text character, that is). */ while (prefix_end != RESET_PATTERN_FLAG && charmap[text[suffix_end]] != charmap[pattern[prefix_end]]) prefix_end = fail_trans_table[prefix_end]; if (prefix_end + 1 >= pattern_len) return 1; else ++suffix_end, ++prefix_end; } /* This conditional expression is used to terminate the search when it becomes clear that we can't match the PATTERN since the TEXT has fewer unexamined characters than the PATTERN length. */ while (text_len - suffix_end >= pattern_len - prefix_end); else /* This loop is identical with the preceding one, except that we don't bother to fold case... */ do { while (prefix_end != RESET_PATTERN_FLAG && text[suffix_end] != pattern[prefix_end]) prefix_end = fail_trans_table[prefix_end]; if (prefix_end + 1 >= pattern_len) return 1; else ++suffix_end, ++prefix_end; } while (text_len - suffix_end >= pattern_len - prefix_end); return 0; } /* The name sez it all! */ void print_usage_and_die (char *prog_name) { fprintf (stderr, "usage: %s [-inv] pattern [file]\n", prog_name); exit (1); } /* Main driver program. Emulates certain useful features of fgrep. */ int main (int argc, char **argv) { GetOpt getopt(argc, argv, "dinv"); if (argc == 1) print_usage_and_die (argv[0]); /* A rather arbitrary limit... */ const int MAX_LINE = 200; char text[MAX_LINE]; int c; /* Initialize any user-specified options. */ while ((c = getopt ()) != EOF) switch (c) { case 'd': option[DEBUG] = 1; break; case 'i': option[FOLD_CASE] = 1; break; case 'n': option[LINE_NUMBERS] = 1; break; case 'v': option[INVERSE] = 1; break; default: print_usage_and_die (argv[0]); } /* Call the constructor to build the failure function table. */ kmp match (argv[getopt.optind], strlen (argv[getopt.optind]), option[DEBUG]); /* Handle a user-specified input file. */ if (argv[++getopt.optind] && !freopen (argv[getopt.optind], "r", stdin)) { perror (argv[0]); return 1; } /* Split the following into two separate cases to avoid overhead when line numbers are not required. */ if (option[LINE_NUMBERS]) { int line; for (line = 1; gets (text); line++) if (match (text, strlen (text)) != option[INVERSE]) printf ("%d:%s\n", line, text); } else { while (gets (text)) if (match (text, strlen (text)) != option[INVERSE]) puts (text); } return 0; } { perror (argv[0]); return 1; } /* Split the following into two separate cases to avolibg++/etc/ADT-examples/tsortinp.cc 600 473 0 473 4677700014 12277 // Here's a short program that generates acyclic input to test this program // against the UNIX tsort. #include main(int argc,char *argv[]) { int Dimension = atoi(argv[1]); for (int y = 1; y < Dimension; y++) for (int x = 0; x < y; x++) cout << dec(y,4) << dec(x,4) << "\n"; } (match (text, strlen (text)) != option[INVERSE]) puts (text); } return 0; } { perror (argv[0]); return 1; } /* Split the following into two separate cases to avolibg++/etc/ADT-examples/keyhash.cc 600 473 0 11232 4677700014 12104 // Date: Tue, 20 Sep 88 01:03:21 -0700 // From: "Douglas C. Schmidt" // // // The following is an Obstack-based program, which outputs all the GCC // reserved words in an input file redirected from cin // In addition, I found a neat use for // derived types by defining a word-by-word input class that is based // upon the class Obstack. Finally, there is the added bonus of seeing // how the O (1) time GCC perfect hash function recognizer from GCC 1.35 // works; I've incorporated the relevant code in this short routine. // Feel free to fold, spindle, or mutilate this code. // #include #include #include #define NIL(TYPE) ((TYPE *)0) class Word_Read : private Obstack { public: Obstack::free; // Allow the derived type to inherit only this member function. // Make the default something reasonable, like 80 columns. Word_Read (int Default_Len = 80): (Default_Len) { ; } // A very rudimentary method for carving out the next word // from the input. Ignores most error conditions. All non- // words are skipped entirely. A word is defined as a // letter, followed by a sequence of letters, digits, and/or // underbars `_'. char *operator ()(int& Len = 0) { char c; while (cin.get (c) && !(isalpha (c) || c == '_')) ; do Obstack::grow (c); while (cin.get (c) && (isalnum (c) || c == '_')); Len = Obstack::size (); return cin.good () ? Obstack::finish (0) : 0; } // Make the destructor print out something useful, like // output a diagnostic. ~Word_Read () { cout << "chunk_size = " << Obstack::chunk_size () << "\n"; cout << "size = " << Obstack::size () << "\n"; cout << "room = " << Obstack::room () << "\n"; } }; // Provides a nice example of the perfect hash function used to recognize // GCC reserved words in O(1) steps. class Lookup_Table { private: const int MIN_WORD_SIZE = 2; const int MAX_WORD_SIZE = 12; const int MIN_KEY_SIZE = 4; const int MAX_KEY_SIZE = 64; static int Hash_Table[] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 1, 64, 9, 17, 15, 28, 19, 29, 15, 64, 2, 64, 64, 25, 4, 16, 22, 40, 64, 11, 23, 1, 1, 16, 2, 64, 64, 8, 64, 64, 64, 64, 64, }; static char *Reswords[] = { "", "", "", "", "if", "", "int", "", "union", "while", "__typeof", "__inline", "__typeof__", "__inline__", "auto", "__asm", "asm", "__asm__", "return", "__alignof", "goto", "__alignof__", "void", "__const", "enum", "__const__", "extern", "__volatile", "char", "__volatile__", "do", "switch", "unsigned", "inline", "register", "double", "const", "sizeof", "static", "continue", "struct", "break", "case", "for", "signed", "long", "else", "typeof", "typedef", "volatile", "short", "", "", "", "", "", "float", "", "", "", "", "", "", "", "default", }; // And here it is.... Very simple, guaranteed to work! int Hash (char *Str,int Len) { switch (Len) { default: case 3: Len += Hash_Table[Str[2]]; case 2: case 1: return Len + Hash_Table[Str[0]]; } } public: // Carries out the O (1) lookup for GCC reserved words! int operator () (char *Str,int Len) { if (Len <= MAX_WORD_SIZE && Len >= MIN_WORD_SIZE) { register int Key = Hash (Str,Len); if (Key >= MIN_KEY_SIZE && Key <= MAX_KEY_SIZE) if (*Reswords[Key] == *Str && !strcmp (Reswords[Key] + 1,Str + 1)) return 1; } return 0; } }; static void Store_Buf (char *Buf) { cout << "Storing reserved word " << Buf << "\n"; // Just kidding! But you get the idea.... } main (int argc, char *argv[]) { Word_Read Get_Next_Word; Lookup_Table Is_Reserved_Word; char *Buf; int Len; while (Buf = Get_Next_Word (Len)) if (Is_Reserved_Word (Buf,Len)) Store_Buf (Buf); // Keep reserved words else Get_Next_Word.free (Buf); // Discard non-reserved words return 0; } } }; static void Store_Buf (char *Buf) { cout << "Storing reserved word " << Buf << "\n"; // Just kidding! But you get the idea.... } main (int argc, char *argv[]) { Word_Read Get_Next_Word; Lookup_Table Is_Reserved_Word; char *Buf; int Len; while (Buf = Get_Next_Word (Len)) if (Is_Reserved_Word (Buf,Len)) Store_Buflibg++/etc/ADT-examples/generic-q.cc 600 473 0 7141 4677700015 12307 // From: "Douglas C. Schmidt" // Date: Sun, 25 Sep 88 16:19:35 -0700 #include #include #include #include #define queue(type) name2(type,queue) #define list(type) name2(type,list) #define queuedeclare(type) \ class queue(type) { \ struct list(type) { \ type item; \ list(type) *next; \ } *head; \ int sz; \ public: \ queue(type)(void) {head = 0;sz = 0;} \ ~queue(type)(void) { \ list(type) *temp; \ while (head) { \ temp = head; \ head = head->next; \ delete temp; \ } \ } \ int empty(void) {return(!head);} \ int size(void) {return(sz);} \ void enqueue(type new_item); \ type front(void) { \ return(head->next->item); \ } \ type dequeue(void); \ }; #define queueimplement(type) \ type queue(type)::dequeue(void) { \ if (head) { \ type temp = head->next->item; \ list(type) *temp_ptr; \ if ((temp_ptr = head->next) == head) { \ head = 0; \ } \ else { \ head->next = temp_ptr->next; \ } \ delete temp_ptr; \ sz--; \ return(temp); \ } \ } \ void queue(type)::enqueue(type new_item) { \ if (!head) { \ head = new list(type); \ head->item = new_item; \ head->next = head; \ } \ else { \ list(type) *temp_node = new list(type); \ temp_node->item = new_item; \ temp_node->next = head->next; \ head->next = temp_node; \ head = temp_node; \ } \ sz++; \ } \ queuedeclare(String); queueimplement(String); queuedeclare(double); queueimplement(double); main() { String Buf; queue(String) Q_String; queue(double) Q_double; while (cin >> Buf) { if (Buf.matches(RXalpha)) { Q_String.enqueue(String(Buf)); } else if (Buf.matches(RXdouble)) { Q_double.enqueue(atof(Buf)); } } while (!Q_String.empty()) { cout << "Size = " << Q_String.size() << ",Item = " << Q_String.front() << "\n"; void(Q_String.dequeue()); } while (!Q_double.empty()) { cout << "Size = " << Q_double.size() << ",Item = " << Q_double.front() << "\n"; void(Q_double.dequeue()); } return (0); } tches(RXalpha)) { Q_String.enqueue(String(Buf)); } else if (Buf.matches(RXdouble)) { Q_double.enqueue(atof(Buf)); } } while (!Q_String.empty()) { cout << "Size = " << Q_String.size() << ",Item = " << Q_String.front() << "\n"; void(Q_String.dequeue()); } while (!Q_double.empty()) { cout << "Size = " << Q_double.size() << ",Item = "libg++/etc/ADT-examples/genPatkey.cc 600 473 0 1101 4677700015 12352 // Generates random character strings #include main (int argc, char *argv[]) { if (argc != 3) { cout << "usage: " << argv [0] << " number-of-keys length-of-keys\n"; return 1; } else { int Key_Number = atoi (argv [1]); int Key_Length = atoi (argv [2]); srandom (getpid()); for (int j = 0; j < Key_Number; j++) { for (int i = 0; i < Key_Length - (random () % 20); i++) cout << char ('!' + random () % (1+'~'-'!')); cout << "\n"; } return 0; } } int argc, char *argv[]) { if (argc != 3) { cout << "usage: " << argv [0] << " number-of-keys length-of-keys\n"; return 1; } else { int Key_Number = atoi (argv [1]); int Key_Length = atoi (argv [2]); srandom (getpid()); for (int j = 0; j < Key_Number; j++) { for (int i = 0; i < Key_Length - (random () % 20); i++) cout << char ('!' + random () % (1+'~'-'!libg++/etc/ADT-examples/Makefile 600 473 0 6254 4677700015 11572 # A makefile for the stuff now in libg++/etc/ADT-examples # ------ source locations # source directory for libg++.a SRCDIR = ../../../src # source include directory SRCIDIR= ../../../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< DEMOS= generic-q search keyhash \ tsort tsortinp genkey patricia kmp all: demos tests demos: $(DEMOS) tests: $(DEMOS) -./generic-q < ./generic-q.cc -./tsortinp 20 | ./tsort -./keyhash < ./keyhash.cc -./search 1000 -./genkey 1000 200 > input -./patricia ./input ./input | grep -v "is found" # -./dhrystone generic-q: generic-q.o $(GXX) generic-q.o $(GXXLDFLAGS) -o generic-q tsort: tsortinp tsort.o $(GXX) tsort.o $(GXXLDFLAGS) -o tsort tsortinp: tsortinp.o $(GXX) tsortinp.o $(GXXLDFLAGS) -o tsortinp keyhash: keyhash.o $(GXX) keyhash.o $(GXXLDFLAGS) -o keyhash search: search.o $(GXX) search.o $(GXXLDFLAGS) -o search genkey: genPatkey.o $(GXX) genPatkey.o $(GXXLDFLAGS) -o genkey Patricia.o: Patricia.h Patmain.o: Patricia.h patricia: Patmain.o Patricia.o $(GXX) Patmain.o Patricia.o $(GXXLDFLAGS) -o patricia kmp: kmp.o $(GXX) kmp.o $(GXXLDFLAGS) -o kmp clean: rm -f *.o $(DEMOS) core input C++.hack* DFLAGS) -o tsort tsortinp: tsortinp.o $(GXX) tsortinp.o $(GXXLDFLAGS) -o tsortinp keyhash: keyhash.o $(GXX) keyhash.o $(GXXLDFLAGS) -o keyhash search: search.o $(GXX) search.o $(GXXLDFLAGS) -o search genkey: genPatkey.o $(GXX) genPatkey.o $(GXXLDFLAGS) -o genkey Patricia.o: Patricia.h Patmain.o: Patricia.h patricia: Patlibg++/etc/ADT-examples/kmp.cc~ 600 473 0 25611 4677700015 11444 //From: "Douglas C. Schmidt" //Date: Fri, 28 Jul 89 11:47:11 -0700 /* Nifty little program that illustrates an implementation of the Knuth, Morris, Pratt string matching algorithm. This program has a user interface similar to fgrep, i.e., when you provide it with a fixed pattern it prints out all the lines from the standard input (or one user-specified input file) that contain at least one substring that matches the provided pattern. Relevant options are: -i: Ignore case when performing comparisons. -n: Print out lines numbers along with the matching lines. -v: Print out lines that *don't* match the pattern. The code below is extensively commented. If these comments distract you, run the code through g++ -E first ;-). */ #include #include /* This array is designed for mapping upper and lower case letter together for a case independent comparison. The mappings are based upon the ASCII character sequences. */ char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; /* The list of available program options. */ enum options { DEBUG, FOLD_CASE, LINE_NUMBERS, INVERSE, OPTION_SIZE }; /* Vector storing the enabled options (all initially disabled). */ char option[OPTION_SIZE]; /* Data and function members necessary to implement the KMP algorithm. */ class kmp { private: #ifdef GNUG const int RESET_PATTERN_FLAG = -1; #else #define RESET_PATTERN_FLAG -1 #endif int *fail_trans_table; /* Stores the generated nfa used when matching. */ char *pattern; /* Stores the user-supplied pattern. */ int pattern_len; /* Pattern length. */ void print_fail_trans_table (void); public: kmp (char *pattern, int pattern_len, int debug = 0); ~kmp () { delete fail_trans_table; } int operator ()(char *text, int text_len); }; /* Provide a debugging dump of the failure function. Nothing fancy... */ void kmp::print_fail_trans_table (void) { int i; for (i = 0; i < pattern_len; i++) printf ("%3d,", i); putchar ('\n'); for (i = 0; i < pattern_len; i++) printf ("%3d,", fail_trans_table [i]); putchar ('\n'); } /* This constructor builds the transition table that encodes the failure function automaton. The table stores the PATTERN index we go to in the event of a mismatch with the input text string. This generation process runs in time linear to the pattern size. The terms SUFFIX and PREFIX used below are defined in terms of each other. That is, at each state of the failure function we seek to determine the largest pattern prefix that matches with the largest suffix in the actual input text. This information informs us how far we can legitimately shift the pattern to the right when a mismatch occurs during the string matching process. Stated more formally, this means that for all i (0 <= i <= (PATTERN_LEN - 1)) FAIL_TRANS_TABLE (i) is the largest j < i, such that PATTERN[1..j - 1] is a suffix of PATTERN[1..i - 1] and PATTERN[i] != PATTERN[j]. */ kmp::kmp (char *pat, int len, int debug): pattern (pat), fail_trans_table (new int[len]), pattern_len (len) { /* Points 1 beyond the rightmost potential *suffix* in the pattern (which is actually simulating the behavior of an actual input text string. */ int suffix_end = 0; /* Points 1 beyond the rightmost potential *prefix* in the pattern. */ int prefix_end = fail_trans_table[suffix_end] = RESET_PATTERN_FLAG; do { /* This WHILE loop uses the precomputed failure function to look further left into the pattern trying to find an index location where the pattern prefix matches the pattern suffix. However, if/when we locate the RESET_PATTERN_FLAG this means that we can just skip ahead to the next character in the input text. */ while (prefix_end != RESET_PATTERN_FLAG && pattern[suffix_end] != pattern[prefix_end]) prefix_end = fail_trans_table[prefix_end]; /* Once SUFFIX_END and PREFIX_END are pre-incremented below we know that the first PREFIX_END characters of PATTERN match the characters in positions PATTERN[SUFFIX_END - PREFIX_END .. SUFFIX_END - 1], i.e., the last PREFIX_END characters in the rightmost part of the first SUFFIX_END - 1 characters in PATTERN. If the character at location PATTERN[SUFFIX_END] matches that at PATTERN[PREFIX_END] it is silly to have the failure transition jump to that pattern location (since it would immediately fail to match, of course!). Instead, in that case we just ``borrow'' the previously computed transition stored at FAIL_TRANS_TABLE[PREFIX_END] and use it. */ if (pattern[++suffix_end] == pattern[++prefix_end]) fail_trans_table[suffix_end] = fail_trans_table[prefix_end]; else fail_trans_table[suffix_end] = prefix_end; } /* Adding the extra 1 here is necessary since C strings are indexed from 0 to pattern_len - 1... */ while (suffix_end + 1 < pattern_len); if (debug) print_fail_trans_table (); } /* Actually perform the KMP matching algorithm using the generated determinisitic pattern matching match encoded in the failure transition table. This version is optimized on the assumption that there will be more characters in the text input that *don't* match the pattern than ones that do match it. Therefore, we make a special effort to keep looping through the failure function as long as the text and pattern don't match. */ int kmp::operator ()(char *text, int text_len) { int suffix_end = RESET_PATTERN_FLAG; int prefix_end = RESET_PATTERN_FLAG; /* If TEXT length is shorted than PATTERN we'll bail out now... */ if (text_len < pattern_len) return 0; /* Split the following two cases so that we don't pay any unnecessary overhead when case folding is not required. */ if (option[FOLD_CASE]) /* Note how this main loop is almost identical with the `failure transition table building' algorithm used above. */ do { /* Ignore case when matching and keep applying the failure function until we get a match or are forced to restart the pattern (starting with the *following* input text character, that is). */ while (prefix_end != RESET_PATTERN_FLAG && charmap[text[suffix_end]] != charmap[pattern[prefix_end]]) prefix_end = fail_trans_table[prefix_end]; if (prefix_end + 1 >= pattern_len) return 1; else ++suffix_end, ++prefix_end; } /* This conditional expression is used to terminate the search when it becomes clear that we can't match the PATTERN since the TEXT has fewer unexamined characters than the PATTERN length. */ while (text_len - suffix_end >= pattern_len - prefix_end); else /* This loop is identical with the preceding one, except that we don't bother to fold case... */ do { while (prefix_end != RESET_PATTERN_FLAG && text[suffix_end] != pattern[prefix_end]) prefix_end = fail_trans_table[prefix_end]; if (prefix_end + 1 >= pattern_len) return 1; else ++suffix_end, ++prefix_end; } while (text_len - suffix_end >= pattern_len - prefix_end); return 0; } /* The name sez it all! */ void print_usage_and_die (char *prog_name) { fprintf (stderr, "usage: %s [-inv] pattern [file]\n", prog_name); exit (1); } /* Main driver program. Emulates certain useful features of fgrep. */ int main (int argc, char **argv) { if (argc == 1) print_usage_and_die (argv[0]); /* Required for getopt. */ extern int optind; /* A rather arbitrary limit... */ const int MAX_LINE = 200; char text[MAX_LINE]; int c; /* Initialize any user-specified options. */ while ((c = getopt (argc, argv, "dinv")) != EOF) switch (c) { case 'd': option[DEBUG] = 1; break; case 'i': option[FOLD_CASE] = 1; break; case 'n': option[LINE_NUMBERS] = 1; break; case 'v': option[INVERSE] = 1; break; default: print_usage_and_die (argv[0]); } /* Call the constructor to build the failure function table. */ kmp match (argv[optind], strlen (argv[optind]), option[DEBUG]); /* Handle a user-specified input file. */ if (argv[++optind] && !freopen (argv[optind], "r", stdin)) { perror (argv[0]); return 1; } /* Split the following into two separate cases to avoid overhead when line numbers are not required. */ if (option[LINE_NUMBERS]) { int line; for (line = 1; gets (text); line++) if (match (text, strlen (text)) != option[INVERSE]) printf ("%d:%s\n", line, text); } else { while (gets (text)) if (match (text, strlen (text)) != option[INVERSE]) puts (text); } return 0; } { perror (argv[0]); return 1; } /* Split the following into two separate cases to avoid overhead libg++/etc/HINTS 644 473 0 46755 4677700016 6561 BABYL OPTIONS: Version: 5 Labels: Note: This is the header of an rmail file. Note: If you are seeing it in rmail, Note: it means the file has no messages in it.  1,, Return-Path: Received: from oswego.Oswego.EDU by g.oswego.edu (4.0/SMI-4.0) id AA08377; Sun, 11 Feb 90 21:33:40 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.21) id AA00896; Sun, 11 Feb 90 21:33:18 EST Received: from raid8.cs.purdue.edu by arthur.cs.purdue.edu (5.61/PURDUE_CS-1.2) id ; Sun, 11 Feb 90 21:30:14 -0500 Received: from localhost by raid8.cs.purdue.edu (5.61/PURDUE_CS-1.2) id ; Sun, 11 Feb 90 21:30:08 -0500 Message-Id: <9002120230.AA19140@raid8.cs.purdue.edu> To: dl@oswego.oswego.edu Subject: kudos for profiling and libg++ In-Reply-To: Your message of Tue, 09 Jan 90 06:27:17 -0500. <9001091127.AA09544@g.oswego.edu> Date: Sun, 11 Feb 90 21:30:04 EST From: riedl@cs.purdue.edu *** EOOH *** Return-Path: To: dl@oswego.oswego.edu Subject: kudos for profiling and libg++ In-Reply-To: Your message of Tue, 09 Jan 90 06:27:17 -0500. <9001091127.AA09544@g.oswego.edu> Date: Sun, 11 Feb 90 21:30:04 EST From: riedl@cs.purdue.edu I was having some trouble with the performance of a concurrency controller I had written, and am very pleased to report that g++ support for profiling, and the excellent libg++ data structure support saved the day! I include a detailed description of the problem and solution below, which you are welcome to send to any of the involved parties for encouragement, or to publish for bragging rights (:-). Nice job! John ------ The basic problem was that two concurrency controllers that I had written, called T/O and Lock for short, should have had similar performance characteristics, but didn't. After some days of work it became clear that T/O was significantly slower than Lock, for reasons that I couldn't understand. I profiled the two routines and found the profiles to be very similar, as expected, with the exception of a large number of calls to compare_item in T/O: calls to compare_item total time T/O 118,112 0.43 10.76 seconds LOCK 6601*[2-3] 0.09 seconds 9.02 seconds (The numbers involved are small because I did the run for 100 transactions. Real runs will be for several orders of magnitude more transactions.) (I don't have an exact number for the number of calls to compare item for Lock for obscure reasons, but my understanding of the program makes me confident that it was called 2-3 times for each call to its parent, which was called 6601 times.) The additional 1.74 seconds spent in T/O could almost all be accounted for by calls to compare_item and its parent, SLSet::seek. Since the data structures involved were relatively small I expected that using a fancier data structure wouldn't help, but I thought I should test the potential. I determined that the data structures involved would grow to about 300 items, and that items would be accessed much more often than they would be inserted. So I timed versions using the linked list and using AVL trees: program items accesses seconds (user time) sl-set 300 10,000 7.70 sl-set 300 10,000 7.61 sl-set 3000 10,000 91.35 avl-set 300 1,000 0.18 avl-set 300 10,000 0.68 avl-set 300 100,000 6.15 avl-set 3000 10,000 1.48 Clearly the AVL tree implementation was far superior, even for small problem sizes. I installed the AVL sets in T/O and they solved the performance problem I was having. Profiling shows that before the change: calls to compare_item total time T/O 118,112 0.43 10.76 seconds LOCK 6601*[2-3] 0.09 seconds 9.02 seconds After the change locking is the same, but: T/O 16,048 0.10 seconds 9.08 seconds The lessons I take from this study are: 1) Linked lists may cause performance problems even if the lists are relatively short (< 100 items) if they are heavily used. 2) The C++ library can be extremely advantageous. In this case, I made a two line change to my program to change to AVL trees. 3) Profiling is essential to understanding program performance. John Riedl  1,, Return-Path: Received: from rocky.Oswego.EDU by g.oswego.edu (4.0/SMI-4.0) id AA03598; Thu, 8 Feb 90 05:50:05 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.21) id AA08592; Thu, 8 Feb 90 05:47:12 EST Received: from life.ai.mit.edu by nisc.nyser.net (5.61/2.1-NYSERNet NISC) id AA07649; Thu, 8 Feb 90 05:44:40 -0500 Received: from oswego.Oswego.EDU by life.ai.mit.edu (4.0/AI-4.10) id AA29896; Thu, 8 Feb 90 05:46:04 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.21) id AA27161; Thu, 8 Feb 90 05:48:41 EST Received: by g.oswego.edu (4.0/SMI-4.0) id AA03595; Thu, 8 Feb 90 05:48:50 EST Date: Thu, 8 Feb 90 05:48:50 EST From: dl@g.oswego.edu (Doug Lea) Message-Id: <9002081048.AA03595@g.oswego.edu> To: jose@csserver.cs.msstate.edu Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Jose Cordova's message of Wed, 7 Feb 90 17:28:57 CST <9002072328.AA07167@CSServer.CS.MsState.Edu> Subject: Run-time error when using 'get' with an istream object Reply-To: dl@oswego.oswego.edu *** EOOH *** Return-Path: Date: Thu, 8 Feb 90 05:48:50 EST From: dl@g.oswego.edu (Doug Lea) To: jose@csserver.cs.msstate.edu Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Jose Cordova's message of Wed, 7 Feb 90 17:28:57 CST <9002072328.AA07167@CSServer.CS.MsState.Edu> Subject: Run-time error when using 'get' with an istream object Reply-To: dl@oswego.oswego.edu > I am having trouble using the 'get' method for the 'istream' class. > It generates a 'Segmentation fault' error at run-time. I know the > 'istream' is being opened correctly because reading into a 'String' > object with >> works fine. Am I doing something wrong ? > The sample program and "data" illustrate the point: > > main() > { > istream from("data",io_readonly,a_useonly); > char *line; > > from.get(line,15); > cout << line; > } > > Sample "data" file contents: > word1 word2 > word3 > There are 3 istream functions for reading char*'s istream& get (char* s, int n, char terminator = '\n'); istream& getline(char* s, int n, char terminator = '\n'); istream& gets (char **s, char terminator = '\n'); The first two *require* an allocated char* (they differ only in how the trailing terminator is handled.) To use them, you must supply either a char[N] or an allocated char*. The third automatically allocates space for you, that you should later delete. For example, main() { istream from("data",io_readonly,a_useonly); char *line = new char[16]; // enough for string + null char line2[16]; char* line3 = 0; // `= 0' so delete'able even if never allocated -- // Not necessary in this example. from.get(line,15); from.get(line2,15); from.gets(&line3,15); // pass in the addr of line3 cout << line; cout << line2; cout << line3; delete line; delete line3; } Using the String class is a very good way to avoid dealing with these kinds of char* allocation and semantics issues. -Doug  1, answered,, Return-Path: Received: from aerospace.aero.org ([130.221.192.10]) by g.oswego.edu (4.0/SMI-4.0) id AA03846; Mon, 5 Feb 90 16:10:27 EST Received: from antares.aero.org by aerospace.aero.org with SMTP (5.61++/6.0.GT) id AA24377 for dl@g.oswego.edu; Mon, 5 Feb 90 13:06:58 -0800 Posted-Date: Mon, 5 Feb 90 13:06:50 PST Received: from merlin.aero.org by antares.aero.org (4.1/SMI-3.2-A4ant) id AA20056 for dl@g.oswego.edu; Mon, 5 Feb 90 13:06:55 PST Message-Id: <9002052106.AA20056@antares.aero.org> Received: by merlin.aero.org (4.1/SMI-3.2-A4) id AA03654 for dl@g.oswego.edu; Mon, 5 Feb 90 13:06:50 PST Date: Mon, 5 Feb 90 13:06:50 PST From: chowkwan@aerospace.aero.org To: dl@g.oswego.edu Subject: Checklist for using Map class *** EOOH *** Return-Path: Posted-Date: Mon, 5 Feb 90 13:06:50 PST Date: Mon, 5 Feb 90 13:06:50 PST From: chowkwan@aerospace.aero.org To: dl@g.oswego.edu Subject: Checklist for using Map class I found your last message of Jan 20 was enough to get me started using the Map class. I'm attaching some notes I made in LaTeX format which are intended to get new users off and running quickly. It's pretty much in the form of a checklist that they can just go down and follow. I was thinking it might be useful to you as a standard response to inquiries for help from neophytes like myself. 0 cut here 0 ----------------><--------------------------------><------------------ 0 0 \documentstyle{article} \title{Implementing Table Lookup Using the GNU Library} \begin{document} \section{Introduction} This note describes how to use the GNU class library Version 1.35.0 to create lookup tables. The advantage of using the GNU library is that the code to implement tables can be quickly generated. Hopefully, the code is also more reliable than what we could write ourselves. In addition, the library provides four different lookup mechanisms. It is relatively easy to ``switch engines'' and use the fastest one for our application. This note augments the ``User's Guide to GNU C++ Library'' by filling in some gaps in the manual. Therefore, it is intended to complement, rather than replace the original manual. Section \ref{sec:general} describes the general procedure for creating a lookup table. Section \ref{sec:specific} gives a working example, in this case the creation of a lookup table for database objects. \section{Using the GNU Library to Create a Lookup Table} \label{sec:general} The GNU library provides four implementations of lookup tables: threaded AVL trees, splay trees, resizable hash tables, and chained hash tables. The hash table implementations provide double hashing. The class names for these implementations are shown below in Table \ref{tab:imp}. All four classes are subclasses of the {\tt Map} class. \\ Therefore, to create a lookup table, you must define a table class based on the abstract class {\tt Map} as well as one of the subclasses. The script {\tt genclass}, provided with the GNU library, automates this process. \begin{table}[htb] \centering \caption{\label{tab:imp} GNU Implementations of Lookup Tables} \begin{tabular}{||l|l||} \hline {\bf Class Name} & {\bf Implementation Method} \\ \hline {\tt AVLMap} & Threaded AVL trees. \\ {\tt SplayMap} & Splay trees. \\ {\tt VHMap} & Resizable hash tables. \\ {\tt CHMap} & Chained hash tables. \\ \hline \end{tabular} \\ \end{table} A {\sl key} refers to the index for the table and {\sl base value} refers to the basic data stored in the table that is returned upon a keyed lookup. You need to define a hashing function and an equality function for the key. Finally, if you use pointers as your base value you need to typedef a name for the pointer. The steps you need to take are shown below. In these examples, {\tt $<$K$>$} is the name of the key class, {\tt $<$B$>$} the name of the class for the base value, {\tt $<$BP$>$} the name of the type pointer to base value, and {\tt $<$M$>$} the name of one of the four {\tt Map} subclasses. \\ \begin{tabular}{||r|l|l||} \hline && {\bf Name of } \\ {\bf Step} & {\bf Action} & {\bf Affected File} \\ \hline 1 & Create functions {\tt $<$K$>$HASH} & {\tt $<$K$>$.defs.h} \\ & and {\tt $<$K$>$EQ}. &{\tt $<$K$>$.defs.cc } \\ \hline 2 & Define {\tt DEFAULT\_INITIAL\_CAPACITY} & {\tt $<$K$>$.defs.h} \\ \hline 3 & Create typedef {\tt $<$BP$>$}. & {\tt $<$B$>$.h} \\ & for pointer to base class. & \\ \hline 4 & Create abstract class with & {\tt $<$K$>$.$<$BP$>$.Map.h} \\ & {\tt genclass -2 $<$K$>$ ref $<$BP$>$ val Map}& {\tt $<$K$>$.$<$BP$>$.Map.cc} \\ \hline 5 & Edit {\tt $<$K$>$.$<$BP$>$.Map.h} to include &{\tt $<$K$>$.$<$BP$>$.Map.h} \\ & {\tt $<$K$>$.defs.h} and {\tt $<$B$>$.h}. & \\ \hline 6 & Create table class for specific & {\tt $<$K$>$.$<$BP$>$.$<$M$>$.h} \\ & lookup implementation method with & {\tt $<$K$>$.$<$BP$>$.$<$M$>$.cc} \\ & {\tt genclass -2 $<$K$>$ ref $<$BP$>$ val $<$M$>$ } & \\ \hline \end{tabular} \\ The {\tt $<$K$>$} and {\tt $<$BP$>$} arguments to {\tt genclass} can be qualified by either {\tt val} or {\tt ref} depending on whether the reference is by value or by reference. \section{Example: Table Lookup Class for Database Objects} \label{sec:specific} In this example, we want to refer to objects from the user-defined class {\tt Database} by their names so the name of the database object is the key to the table. To accommodate the {\tt Map} class need for hashing on the key, the name is represented by a {\tt String} and the hash function is the library {\tt hashpjw} function declared in {\tt builtin.h} Thus {\tt $<$K$>$} is {\tt String}, {\tt $<$B$>$} is {\tt Database}, and {\tt $<$BP$>$} is {\tt Databasep}. For this example, the lookup mechanism used is resizable hash tables which have type {\tt VHMap} so {\tt $<$M$>$} is {\tt VHMap}. \begin{enumerate} \item The {\tt Map} classes expect to get a function called {\tt HStringHASH} that takes an argument of type {\tt String} so {\tt hashpjw} was wrapped inside {\tt HStringHASH}. Similarly, {\tt HStringEQ} is a wrapper for the {\tt HString} class operator $=$. (The $=$ operator is inherited from the {\tt String} class). The function headers for {\tt HStringHASH} and {\tt HStringEQ} go into {\tt HString.defs.h} and the function bodies into {\tt HString.defs.cc}. \item {\tt DEFAULT\_INITIAL\_CAPACITY} was set to {\tt 1021} in {\tt HString.defs.h}. You must use the identifier {\tt DEFAULT\_INITIAL\_CAPACITY} to be consistent with the {\tt Map} classes. \item Define {\tt Databasep} as a pointer to class {\tt Database} in {\tt Database.h}. An identifier other than {\tt Databasep} would also be acceptable. You just can't use {\tt Database*}. \item {\tt genclass -2 HString ref Databasep val Map} \\ produces {\tt HString.Databasep.Map.h} and \\ {\tt HString.Databasep.Map.cc}. \item Edit {\tt HString.Databasep.Map.h} to include {\tt HString.defs.h} and \\ {\tt Database.h}. \item {\tt genclass -2 HString ref Databasep val VHMap} \\ produces {\tt HString.Databasep.VHMap.h} and \\ {\tt HString.Databasep.VHMap.cc}. \end{enumerate} \end{document}  1,, Return-Path: Received: from rocky.Oswego.EDU by g.oswego.edu (4.0/SMI-4.0) id AA26086; Sat, 3 Feb 90 07:05:17 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.19) id AA09020; Sat, 3 Feb 90 07:04:44 EST Received: from life.ai.mit.edu by nisc.nyser.net (5.61/2.1-NYSERNet NISC) id AA24615; Sat, 3 Feb 90 07:00:07 -0500 Received: from oswego.Oswego.EDU by life.ai.mit.edu (4.0/AI-4.10) id AA04153; Sat, 3 Feb 90 07:00:15 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.19) id AA16111; Sat, 3 Feb 90 07:02:52 EST Received: by g.oswego.edu (4.0/SMI-4.0) id AA26081; Sat, 3 Feb 90 07:03:03 EST Date: Sat, 3 Feb 90 07:03:03 EST From: dl@g.oswego.edu (Doug Lea) Message-Id: <9002031203.AA26081@g.oswego.edu> To: ngo%tammy@harvard.harvard.edu Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Tom Ngo's message of Fri, 2 Feb 90 23:42:54 EST <9002030548.AA00886@life.ai.mit.edu> Subject: Should "operator =" be made to return *this, by convention? Reply-To: dl@oswego.oswego.edu *** EOOH *** Return-Path: Date: Sat, 3 Feb 90 07:03:03 EST From: dl@g.oswego.edu (Doug Lea) To: ngo%tammy@harvard.harvard.edu Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Tom Ngo's message of Fri, 2 Feb 90 23:42:54 EST <9002030548.AA00886@life.ai.mit.edu> Subject: Should "operator =" be made to return *this, by convention? Reply-To: dl@oswego.oswego.edu > > C programmers are accustomed to expecting = to return the value > assigned. However, in a few classes--for example, String, Integer > and Rational-- operator == returns void. Is there a good reason > for this? Could they be made to return String&, Integer& and > Rational& *this without causing problems? > The reason that X= (+=, -=, etc.) and = operators return void is to facilitate simple subclassing. While `utility' classes like String, Integer, etc., are not designed for extensive subclassing (since no members are virtual (which, in turn is motivated by efficiency considerations)), it is often convenient to create simple subclasses like class Line : public String. If you do this, then it is most desirable that inherited operators return void. Otherwise, unexpected type matches often occur. For example, if operator << (ostream&, Line&) were redefined for Line, but op += were inherited from String, and had return value String&, then { Line l; ...; cout << (l += "\n"); } would invoke op << (ostream&, String&), which is probably not what anyone would have in mind. This is avoided by having String::+= return void, making this usage illegal. Problems like this outweigh the syntactic convenience of supporting multiple right-associative uses of X= and =. A good rule of thumb about all this is that no non-virtual member functions should ever return *this by reference. (This rule is broken in a few places in libg++ for various reasons though.) -Doug  1,, Return-Path: Received: from rocky.Oswego.EDU by g.oswego.edu (4.0/SMI-4.0) id AA00741; Thu, 18 Jan 90 06:01:53 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.18) id AA22159; Thu, 18 Jan 90 06:02:51 EST Received: from life.ai.mit.edu by nisc.nyser.net (5.61/2.1-NYSERNet NISC) id AA22988; Thu, 18 Jan 90 05:56:52 -0500 Received: from oswego.Oswego.EDU by life.ai.mit.edu (4.0/AI-4.10) id AA00267; Thu, 18 Jan 90 05:58:24 EST Received: by oswego.Oswego.EDU (5.57/Osw4.1.18) id AA16327; Thu, 18 Jan 90 06:01:51 EST Received: by g.oswego.edu (4.0/SMI-4.0) id AA00738; Thu, 18 Jan 90 06:00:57 EST Date: Thu, 18 Jan 90 06:00:57 EST From: dl@g.oswego.edu (Doug Lea) Message-Id: <9001181100.AA00738@g.oswego.edu> To: allen@sscvx1.ssc.gov Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Michael Allen's message of Wed, 17 Jan 90 14:56:32 CST <9001172056.AA01056@mdtf05.gov> Subject: compiling libg++-1.36.3 with g++-1.36.3 on sun4 Reply-To: dl@oswego.oswego.edu *** EOOH *** Return-Path: Date: Thu, 18 Jan 90 06:00:57 EST From: dl@g.oswego.edu (Doug Lea) To: allen@sscvx1.ssc.gov Cc: bug-lib-g++@prep.ai.mit.edu In-Reply-To: Michael Allen's message of Wed, 17 Jan 90 14:56:32 CST <9001172056.AA01056@mdtf05.gov> Subject: compiling libg++-1.36.3 with g++-1.36.3 on sun4 Reply-To: dl@oswego.oswego.edu > 2) several files get flagged as a warning that a volatile funtion does > return, which appears to be false. Not quite false, but deserving of explanation: libg++ does not (yet) use the experimental g++ exception handling facilities (they are still too new: Too many things would have to be redone if the EH features change). So the only exception strategy is for error traps like Integer::error() to call the function pointed to by lib_error_handler (see builtin.h). By default, this points to default_two_arg_error_handler, which prints a message on stderr and aborts. But it *can* be reset to do anything at all, and need not abort execution. On the other hand, *some* (not all) error() member functions are used in a way that preclude any kind of sensible continuation even if error() returns. I mark these as `volatile', since the compiler might as well act as if they cannot return: This is defensible in that even if (*lib_error_handler) returns, things are going so wrong that you are no worse off if the compiler generates (usually faster) code assuming execution aborts. The compiler correctly warns about these. Again, saner strategies will be employed when the C++ exception handling situation stabilizes. -Doug a way that precludelibg++/etc/PlotFile3D/PlotFile3D.h 644 473 0 13315 4677700017 11717 // Header file for PlotFile3D class -*- C++ -*- /* Copyright (C) 1990 Free Software Foundation written by J. Thomas Ngo, Harvard University This file is part of the GNU C++ Library. The GNU C++ Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute The GNU C++ Library, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with The GNU C++ Library so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _PlotFile3D_h #pragma once #define _PlotFile3D_h 1 //=========================================================================== // Top-level declarations //=========================================================================== #include #include #include #include #include class PlotFile3D : private PlotFile { protected: // constant implementation parameters const int umini = 0; // Plot limits to send to 2D package const int vmini = 0; const int umaxi = 3120; const int vmaxi = 3120; const double margin = 0.9; // How much leeway to give on edge of pic // internal state Vec3D intp; // Internal idea of where cursor is in 3D bool valid3D; // true if 3D cursor valid bool stereo; // true for stereo images int stereo_offset; // Stereo separation in pixels (computed) Vec3D ul,vl,wl; // Basis vectors for the left or main image Vec3D ur,vr,wr; // Basis for alternate image, if stereo double scale; // Amount by which to stretch u,v to fit double uorig, vorig; // Offset for scaled u, v double* sintab; // tables, needed by circle, sphere double* costab; int ppq; // points per quadrant in current table // helper functions // project 3D into 2D void project(int&, int&, const Vec3D&, const Vec3D&, const Vec3D& rel) const; // All clipping handled here void line2D(const int u0, const int v0, const int u1, const int v1); // Methods to handle state of 3D cursor: defined or undefined void define3D(); void undefine3D(); void must_be_valid3D(); public: PlotFile3D(FILE* fp, const bool stereo =FALSE, const double th =M_PI/12, const double ph =M_PI/3); ~PlotFile3D(); // plot commands taking Vec3D args PlotFile3D& space (const Vec3D& p0, const Vec3D& p1); PlotFile3D& move (const Vec3D& p); PlotFile3D& cont (const Vec3D& p); PlotFile3D& line (const Vec3D& p0, const Vec3D& p1); PlotFile3D& point (const Vec3D& p); PlotFile3D& box (const Vec3D& p0, const Vec3D& p1); PlotFile3D& circle(const Vec3D& center, const Vec3D& radius, const int points_per_quadrant =10 ); // This one has no PlotFile analog PlotFile3D& sphere(const Vec3D& center, const Vec3D& radius, const int points_per_quadrant =10 ); // versions taking raw coordinates PlotFile3D& space (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1); PlotFile3D& move (const double xi, const double yi, const double zi); PlotFile3D& cont (const double xi, const double yi, const double zi); PlotFile3D& line (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1); PlotFile3D& point (const double xi, const double yi, const double zi); PlotFile3D& box (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1); PlotFile3D& circle(const double cx, const double cy, const double cz, const double rx, const double ry, const double rz, const int points_per_quadrant =10 ); PlotFile3D& sphere(const double cx, const double cy, const double cz, const double rx, const double ry, const double rz, const int points_per_quadrant =10 ); // For convenience PlotFile3D& home(); // Move cursor to upper left, out of the way // These plot commands get passed right to PlotFile PlotFile3D& erase(); PlotFile3D& label(const char* s); PlotFile3D& linemod(const char* s); // Error handling volatile void error(const char* s) const; }; inline void PlotFile3D::define3D() { valid3D = TRUE; } inline void PlotFile3D::undefine3D() { valid3D = FALSE; } inline void PlotFile3D::must_be_valid3D() { assert(valid3D); } inline PlotFile3D& PlotFile3D::line(const Vec3D& p0, const Vec3D& p1) { move(p0); return cont(p1); } inline PlotFile3D& PlotFile3D::point(const Vec3D& p) { return line(p, p); } inline PlotFile3D& PlotFile3D::erase() { PlotFile::erase(); return home(); } inline PlotFile3D& PlotFile3D::label(const char* s) { PlotFile::label(s); return home(); } inline PlotFile3D& PlotFile3D::linemod(const char* s) { PlotFile::linemod(s); return *this; } #endif // _PlotFile3D_h 3D); } inline PlotFile3D& PlotFile3D::line(const Vec3D& p0, const Vec3D& p1) { move(p0); return cont(p1); } inline PlotFile3D& PlotFile3D::point(const Vec3D& p) { return line(p, p); } inline PlotFile3D& PlotFile3D::erase() { PlotFile::erase(); return home(); } inline PlotFile3D& PlotFile3D::libg++/etc/PlotFile3D/PlotFile3D.cc 644 473 0 31222 4677700017 12052 // Source file for PlotFile3D class -*- C++ -*- /* Copyright (C) 1990 Free Software Foundation written by J. Thomas Ngo, Harvard University This file is part of the GNU C++ Library. The GNU C++ Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute The GNU C++ Library, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with The GNU C++ Library so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ // An analog of the PlotFile class, but written for 3D graphics. In // the initializer you specify a camera location, and decide whether // you want stereo viewing. Most other methods are analogous to the // unix plot(3) commands, except that they take 3D positions. #include "PlotFile3D.h" // Error handling volatile void PlotFile3D::error(const char* s) const { (*lib_error_handler)("PlotFile3D",s); } //=========================================================================== // Constructor //=========================================================================== static void _find_basis(Vec3D& u, Vec3D& v, Vec3D& w, const double th, const double ph) { double sth = sin(th), cth = cos(th); double sph = sin(ph), cph = cos(ph); u = Vec3D( sph, cph, 0 ); v = Vec3D( -sth * cph, sth * sph, cth ); w = u ^ v; } PlotFile3D::PlotFile3D(FILE* fp, const bool st, const double th, const double ph) : PlotFile(fp), stereo(st), ppq(0), valid3D(FALSE) { if( stereo ) { const double stereo_separation = 2.5 * M_PI / 180.0; _find_basis( ul,vl,wl, th, ph-stereo_separation ); _find_basis( ur,vr,wr, th, ph+stereo_separation ); } else { _find_basis( ul,vl,wl, th, ph ); ur = ul; vr = vl; wr = wl; } home(); } // destructor PlotFile3D::~PlotFile3D() { if (ppq != 0) { delete sintab; delete costab; } } //=========================================================================== // Set plot limits via space() //=========================================================================== PlotFile3D& PlotFile3D::space(const Vec3D& pt0, const Vec3D& pt1) { // Set up 2D plot package PlotFile::space(umini,vmini,umaxi,vmaxi); // Find 2D rectangle bounding the box specified by user double umin = (pt0.x() * ul.x()) ? (pt0.x() * ur.x()) >? (pt1.x() * ul.x()) >? (pt1.x() * ur.x()); double vmin = (pt0.x() * vl.x()) ? (pt0.x() * vr.x()) >? (pt1.x() * vl.x()) >? (pt1.x() * vr.x()); umin += (pt0.y() * ul.y()) ? (pt0.y() * ur.y()) >? (pt1.y() * ul.y()) >? (pt1.y() * ur.y()); vmin += (pt0.y() * vl.y()) ? (pt0.y() * vr.y()) >? (pt1.y() * vl.y()) >? (pt1.y() * vr.y()); umin += (pt0.z() * ul.z()) ? (pt0.z() * ur.z()) >? (pt1.z() * ul.z()) >? (pt1.z() * ur.z()); vmin += (pt0.z() * vl.z()) ? (pt0.z() * vr.z()) >? (pt1.z() * vl.z()) >? (pt1.z() * vr.z()); // Map this rectangle on to umini et al. using as much space as // possible and centering. Also, if stereo was requested, split // the window right down the middle and try to fit the picture in. int pixwidth = umaxi - umini; int pixheight = vmaxi - vmini; if (stereo) pixwidth /= 2; double uscale = pixwidth / (umax-umin); double vscale = pixheight / (vmax-vmin); if (uscale <= vscale) scale = uscale; else { scale = vscale; pixwidth = int(pixwidth * vscale/uscale); } scale *= margin; uorig = 0.5 * (pixwidth - scale*(umin+umax)); vorig = 0.5 * (pixheight - scale*(vmin+vmax)); if (stereo) stereo_offset = pixwidth; // Set state appropriately return home(); } //=========================================================================== // move() and cont() are used as primitives by the other routines //=========================================================================== PlotFile3D& PlotFile3D::move(const Vec3D& p) { intp = p; define3D(); return *this; } void PlotFile3D::project(int& ui,int& vi, const Vec3D& u, const Vec3D& v, const Vec3D& rel) const { ui = int(rel * u * scale + uorig); vi = int(rel * v * scale + vorig); } static inline bool _clip(int& a, const int amin, const int amax, int& b, const int afar, const int bfar) { double frac = 0; if( a < amin ) { if( afar <= amin ) return FALSE; frac = ((double)amin-a)/(afar-a); a = amin; } else if( a > amax ) { if( afar >= amax ) return FALSE; frac = ((double)amax-a)/(afar-a); a = amax; } if( frac != 0 ) b += int(frac*(bfar-b)); return TRUE; } void PlotFile3D::line2D(int u0, int v0, int u1, int v1) { // Clip against each edge in turn if( !_clip(u0,umini,umaxi,v0,u1,v1) ) return; if( !_clip(v0,vmini,vmaxi,u0,v1,u1) ) return; if( !_clip(u1,umini,umaxi,v1,u0,v0) ) return; if( !_clip(v1,vmini,vmaxi,u1,v0,u0) ) return; // Draw clipped segment PlotFile::move(u0,v0); PlotFile::cont(u1,v1); } PlotFile3D& PlotFile3D::cont(const Vec3D& p) { must_be_valid3D(); int u0, v0, u1, v1; if (stereo) { project(u0,v0, ul,vl, intp); project(u1,v1, ul,vl, p); line2D(u0,v0,u1,v1); project(u0,v0, ur,vr, intp); u0 += stereo_offset; project(u1,v1, ur,vr, p); u1 += stereo_offset; line2D(u0,v0,u1,v1); } else { project(u0,v0, ul,vl, intp); project(u1,v1, ul,vl, p); line2D(u0,v0,u1,v1); } intp = p; return *this; } //=========================================================================== // These last commands are generated by sequences of move() and cont() //=========================================================================== PlotFile3D& PlotFile3D::box(const Vec3D& p0, const Vec3D& p1) { // The corners: Vec3D x0y0z1 (p0.x(),p0.y(),p1.z()); Vec3D x0y1z0 (p0.x(),p1.y(),p0.z()); Vec3D x0y1z1 (p0.x(),p1.y(),p1.z()); Vec3D x1y0z0 (p1.x(),p0.y(),p0.z()); Vec3D x1y0z1 (p1.x(),p0.y(),p1.z()); Vec3D x1y1z0 (p1.x(),p1.y(),p0.z()); // Bottom rectangle move(p0); cont(x1y0z0); cont(x1y1z0); cont(x0y1z0); cont(p0); // One leg cont(x0y0z1); // Top rectangle cont(x1y0z1); cont(p1); cont(x0y1z1); cont(x0y0z1); // Three other legs line(x1y0z0, x1y0z1); line(x1y1z0, p1); line(x0y1z0, x0y1z1); // Set state undefine3D(); return *this; } PlotFile3D& PlotFile3D::circle(const Vec3D& center, const Vec3D& rad, const int points_per_quadrant ) { int i; // Build trig lookup table if necessary if( ppq != points_per_quadrant ) { if( ppq != 0 ) { delete sintab; delete costab; } ppq = points_per_quadrant; sintab = new double[ppq]; costab = new double[ppq]; for( i=0; i main() { PlotFile3D foo(fopen("test.pl", "w")); foo.space(-1000,-1000,-1000,1000,1000,1000).erase(); // Draw and label foo.linemod("longdashed").box(-1000,-1000,-1500,1000,1000,0); foo.linemod("solid").sphere(0,0,500,0,0,500,30); foo.linemod("dotted").circle(0,0,500,0,0,800,50); char title[] = "Test of PlotFile3D package"; foo.home().label(title); } #endif // Test program //=========================================================================== #ifdef TEST #include main() { PlotFile3D foo(fopen("test.pl", "w")); foo.space(-1000,-1000,-1000,1000,1000,1000).erase(); // Draw and label foo.linemod("longdashed").box(-1000,-1000,-1500,1000,1000,0); foo.linemod("solid").sphere(0,0,500,0,0,5libg++/etc/PlotFile3D/tPlotFile3D.cc 644 473 0 622 4677700027 12177 #include main() { PlotFile3D foo(fopen("test.pl", "w")); foo.space(-1000,-1000,-1000,1000,1000,1000).erase(); // Draw and label foo.linemod("longdashed").box(-1000,-1000,-1500,1000,1000,0); foo.linemod("solid").sphere(0,0,500,0,0,500,30); foo.linemod("dotted").circle(0,0,500,0,0,800,50); char title[] = "Test of PlotFile3D package"; foo.home().label(title); } el foo.linemod("longdashed").box(-1000,-1000,-1500,1000,1000,0); foo.linemod("solid").sphere(0,0,500,0,0,5libg++/etc/PlotFile3D/Vec3D.h 644 473 0 12142 4677700030 10706 // Header file for Vec3D class -*- C++ -*- /* Copyright (C) 1990 Free Software Foundation written by J. Thomas Ngo, Harvard University This file is part of the GNU C++ Library. The GNU C++ Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute The GNU C++ Library, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with The GNU C++ Library so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef _Vec3D_h #pragma once #define _Vec3D_h 1 #include #include //=========================================================================== // This class is used by PlotFile3D //=========================================================================== class Vec3D { protected: double n[3]; public: // Constructors and destructor Vec3D(); // initialize to (0,0,0) Vec3D(const double x, const double y, const double z); Vec3D(const Vec3D& that); ~Vec3D(); // Assignment operators Vec3D& operator = ( const Vec3D& that ); Vec3D& operator += ( const Vec3D& that ); Vec3D& operator -= ( const Vec3D& that ); Vec3D& operator *= ( const double that ); Vec3D& operator /= ( const double that ); // You can read, but not set coordinates individually: double operator [] (const int i) const; // Vector notation double x() const; // Point notation double y() const; double z() const; // Error handling volatile void error(const char* s) const; }; // associated operators defined inline below double mod(const Vec3D& x); // sqrt of sum of squares Vec3D operator - (const Vec3D& a); Vec3D operator + (const Vec3D& a, const Vec3D& b); Vec3D operator - (const Vec3D& a, const Vec3D& b); Vec3D operator * (const Vec3D& a, const double sc); // scale double operator * (const Vec3D& a, const Vec3D& b); // dot Vec3D operator ^ (const Vec3D& a, const Vec3D& b); // cross prod int operator == (const Vec3D& a, const Vec3D& b); int operator != (const Vec3D& a, const Vec3D& b); // Error handling inline volatile void Vec3D::error(const char* s) const { (*lib_error_handler)("Vec3D",s); } inline Vec3D::Vec3D() { n[0] = n[1] = n[2] = 0; } inline Vec3D::Vec3D(const double x, const double y, const double z) { n[0]=x; n[1]=y; n[2]=z; } inline Vec3D::Vec3D(const Vec3D& that) { n[0] = that.n[0]; n[1] = that.n[1]; n[2] = that.n[2]; } inline Vec3D::~Vec3D() {} inline Vec3D& Vec3D::operator = (const Vec3D& that) { n[0] = that.n[0]; n[1] = that.n[1]; n[2] = that.n[2]; return *this; } inline const double Vec3D::operator [] (const int i) const { if( i<0 || i>2 ) error("index out of range"); return n[i]; } inline const double Vec3D::x() const { return n[0]; } inline const double Vec3D::y() const { return n[1]; } inline const double Vec3D::z() const { return n[2]; } inline Vec3D operator - (const Vec3D& a) { return Vec3D( -a.x(), -a.y(), -a.z() ); } inline double mod(const Vec3D& p) { return sqrt(sqr(p.x()) + sqr(p.y()) + sqr(p.z())); } inline Vec3D operator + (const Vec3D& a, const Vec3D& b) { return Vec3D( a.x()+b.x(), a.y()+b.y(), a.z()+b.z() ); } inline Vec3D operator - (const Vec3D& a, const Vec3D& b) { return Vec3D( a.x()-b.x(), a.y()-b.y(), a.z()-b.z() ); } inline Vec3D operator * (const Vec3D& a, const double sc) // scale { return Vec3D( a.x()*sc, a.y()*sc, a.z()*sc ); } inline double operator * (const Vec3D& a, const Vec3D& b) // dot { return a.x()*b.x() + a.y()*b.y() + a.z()*b.z(); } inline Vec3D operator ^ (const Vec3D& a, const Vec3D& b) // cross { return Vec3D(a.y()*b.z() - a.z()*b.y(), // UK style a.z()*b.x() - a.x()*b.z(), // notation a.x()*b.y() - a.y()*b.x()); } inline Vec3D& Vec3D::operator += ( const Vec3D& that ) { n[0] += that.x(); n[1] += that.y(); n[2] += that.z(); return *this; } inline Vec3D& Vec3D::operator -= ( const Vec3D& that ) { n[0] -= that.x(); n[1] -= that.y(); n[2] -= that.z(); return *this; } inline Vec3D& Vec3D::operator *= ( const double that ) { n[0] *= that; n[1] *= that; n[2] *= that; return *this; } inline Vec3D& Vec3D::operator /= ( const double that ) { n[0] /= that; n[1] /= that; n[2] /= that; return *this; } inline int operator == (const Vec3D& a, const Vec3D& b) { return a.x() == b.x() && a.y() == b.y() && a.z() == b.z(); } inline int operator != (const Vec3D& a, const Vec3D& b) { return !(a == b); } #endif // _Vec3D_h turn *this; } inline Vec3D& Vec3D::operator *= ( const double that ) { n[0] *= that; n[1] *= that; n[2] *= that; return *this; } inline Vec3D& Vec3D::operator /= ( const double that ) { n[0] /= that; n[1] /= that; n[2] /= that; return *this; } inline int operator == (const Vec3D& a, const Vec3D& b) { return a.x() == b.x() && a.y() == b.y() && a.z() == b.z(); } inline int operator != (conslibg++/etc/PlotFile3D/Makefile 644 473 0 4753 4677700030 11262 # A makefile for the stuff now in libg++/etc # ------ source locations # source directory for libg++.a SRCDIR = ../../src # source include directory SRCIDIR= ../../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/gnu # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) -I. GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) -I. $(GXXFLAGS) -c $< RM = rm -f test: tPlotFile3D ./tPlotFile3D @echo use plot to look at the plot file test.pl tPlotFile3D: PlotFile3D.o tPlotFile3D.o $(GXX) $(GXXFLAGS) tPlotFile3D.o PlotFile3D.o $(GXXLDFLAGS) -o tPlotFile3D clean: rm -f *.o *~ \#* *.bak *.pl tPlotFile3D flags GXXLDFLAGS = -libg++/etc/PlotFile3D/PlotFile3D.inf 644 473 0 10760 4677700030 12240 INFO ABOUT PlotFile3D: The `PlotFile3D' class is similar to the `PlotFile' class, except that it draws 3D pictures using a simple orthogonal projection. Here are some features and limitations: + mono and stereo modes + viewport clipping of all lines and curves (but not text) - static wireframes only; no real-time rotation or hidden-line removal For the most part, the methods of PlotFile3D are extensions of their 2D counterparts in PlotFile, with x,y,z arguments substituted for x,y arguments where appropriate. Unlike coordinates in the 2D class, which (by imitation of the standard Unix plot(3) library) are all of type `int', the coordinates in PlotFile3D are of type double. As with the PlotFile class, all user-visible methods return *this. Exceptions to these rules of thumb are listed in the remainder of this section. Constructor =========== PlotFile3D(FILE *fp, const bool stereo =FALSE, const double th =PI/12, const double ph =PI/3) fp obtained via fopen() or popen() th elevation of camera above xy plane (in radians) ph rotation of 3D scene about the z axis (in radians) stereo TRUE if you want a pair of stereo images, side by side Once specified, the camera's location cannot be changed. Specification of picture dimensions =================================== space(const double x0, const double y0, const double z0 const double x1, const double y1, const double z1) These six coordinates specify a box which would bound the picture in 3D space. PlotFile3D uses this to compute a transformation that makes the picture fit nicely in the square 2D viewing frame. Shape specifications ==================== The methods arc() and dot(), which are available in the PlotFile class, are not available in PlotFile3D. The parameter list of circle() is modified to accommodate three dimensions: circle(const double cx, const double cy, const double cz, const double rx, const double ry, const double rz, const int points_per_quadrant =10) cx,cy,cz specify the center of the circle rx,ry,rz form a vector whose direction is normal to the plane of the circle and whose magnitude is its radius The final optional parameter specifies the number of points to be computed in each quadrant. If (points_per_quadrant == n), then the circle that is drawn is a regular (4*n)-gon. Two of the methods in PlotFile3D have no counterpart in PlotFile. (Yet more might be added if it seems appropriate to break with the PlotFile class philosophy of providing a no-frills package that mirrors the Unix plot(3) package as closely as possible.) These are: sphere(const double cx, const double cy, const double cz, const double rx, const double ry, const double rz, const int points_per_quadrant =10) These arguments are identical to those expected by circle(). The circle specified is the equator of the sphere, which is all that is needed to specify it completely. home() Moves the cursor to a location close to the upper left corner of the viewing frame. Is automatically called by the constructor and by space() and erase(). This method is useful when plotting on devices which leave a visible cursor at the point most recently drawn. It may also be used to place a title label. It should not be used to specify a starting point for a cont() operation since it leaves the 3D cursor location undefined. The remaining methods are completely analogous to their 2D counterparts in the PlotFile class: move(), cont(), line(), point(), box(), erase(), linemod(), label(). When the 3D cursor location is defined ====================================== The cont() and label() methods start drawing at PlotFile3D's internal notion of the "current" location in three dimensions. In many situations, this 3D cursor location is undefined. * It is UNDEFINED immediately after construction, space() and erase(). * It is DEFINED immediately after move(), cont(), line() and point(). * It is UNDEFINED immediately after box(), circle() and sphere() because the manner in which such shapes are drawn is implementation-dependent. * It is UNDEFINED immediately after home() and label() because those are fundamentally 2D operations. * It is unaffected after linemod(). The 3D cursor location must be defined before any cont() operation. If defined, the 3D cursor location determines the location of any text drawn by label(). ter move(), contlibg++/tests/Makefile 644 473 0 64461 4700626770 7773 # Makefile for g++ library test files # Copyright (C) 1988 Free Software Foundation # written by Doug Lea (dl@rocky.oswego.edu) # This file is part of GNU CC. # GNU CC is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. No author or distributor # accepts responsibility to anyone for the consequences of using it # or for whether it serves any particular purpose or works at all, # unless he says so in writing. Refer to the GNU CC General Public # License for full details. # Everyone is granted permission to copy, modify and redistribute # GNU CC, but only under the conditions described in the # GNU CC General Public License. A copy of this license is # supposed to have been given to you along with GNU CC so you # can know your rights and responsibilities. It should be in a # file named COPYING. Among other things, the copyright notice # and this notice must be preserved on all copies. # make parameters -- these should normally be inherited from parent make # ------ source locations # source directory for libg++.a SRCDIR = ../src # source include directory SRCIDIR= ../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/local # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags #OSFLAG= OSFLAG = -DUSG # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install #INSTALL=install -c INSTALL=cp # ranlib if necessary RANLIB=gnuranlib #RANLIB=ranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld -L$(SRCDIR) # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages #VERBOSITY_FLAGS= -Wall -v VERBOSITY_FLAGS= GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags #GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) GXXLDFLAGS = -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< GENCLASS=./genclass all: checktests $(GENCLASS): ../genclass.sh echo "/^PROTODIR=/c\\" > sedscript echo "PROTODIR=$(SRCIDIR)" >> sedscript sed < ../genclass.sh > ./genclass -f sedscript chmod 0755 genclass rm -f sedscript # compilation notes: # The following g++ warnings are expected to appear: # # 1. In twrapper.cc and tgcwrapper.cc, warnings about lazy prototyping # and inability to inline large functions. # # 2. Several warnings from genclass about classes with only .h, no .cc files # # 3. A few harmless reminder warnings that some classes have no data members. # # 4. Many harmless warnings that arguments to vector-delete are unnecessary # when deleting arrays of builtin types. # # Some of the tests output CPU processing time information. These # figures are interesting, but are not always reliable guides # to relative efficiencies of classes in practice, since the # test files sometimes intentionally put code through worst-case # situations, call infrequently used functions, etc. # # test files TSRCS = tFile.cc tObstack.cc tString.cc \ tInteger.cc twrapper.cc tgwrapper.cc tRational.cc \ tComplex.cc tBitSet.cc tBitString.cc tRandom.cc tList.cc tPlex.cc tLList.cc \ tVec.cc tStack.cc tQueue.cc tDeque.cc tPQ.cc tSet.cc tBag.cc \ tMap.cc tFix.cc tFix16.cc tFix24.cc \ test.hello.cc test.bye.cc test.bye2.cc test.shell.cc \ tCurses.cc tGetOpt.cc # executables TOUTS = test0 tFile tObstack tString \ tInteger twrapper tgwrapper tRational tComplex tBitSet tBitString \ tRandom tFix tFix16 tFix24 tCurses tGetOpt \ tList tPlex tLList tVec tStack tQueue tDeque tPQ tSet \ tBag tMap # files for archived prototype classes LOBJS = \ iList.o iSLList.o iDLList.o iVec.o iAVec.o \ iPlex.o iFPlex.o iXPlex.o iRPlex.o iMPlex.o \ iSet.o iBag.o iMap.o iPQ.o \ iXPSet.o iOXPSet.o iSLSet.o iOSLSet.o iBSTSet.o \ iAVLSet.o iSplaySet.o iVHSet.o iVOHSet.o iCHSet.o \ iXPBag.o iOXPBag.o iSLBag.o iOSLBag.o iSplayBag.o \ iVHBag.o iCHBag.o \ iVHMap.o iCHMap.o iSplayMap.o iAVLMap.o \ iRAVLMap.o \ iSplayPQ.o iPHPQ.o iXPPQ.o \ iVStack.o \ iVQueue.o LHDRS = \ idefs.h \ iXPStack.h iSLStack.h \ iXPQueue.h iSLQueue.h \ iXPDeque.h iDLDeque.h \ iStack.h iQueue.h iDeque.h tests: $(SRCDIR)/libg++.a $(GENCLASS) $(TOUTS) runtests: tests for i in $(TOUTS); do \ case $$i in \ test0) echo "Must run test0 from tty";; \ tCurses) echo "Must run tCurses from tty" ;; \ tGetOpt) echo $$i; ./$$i -abc -de10 -2000 -h3i ;; \ *) echo $$i; ./$$i < $$i.inp;; \ esac \ done checktests: tests -$(MAKE) -s runtests > my.out 2>&1 -diff -b expected.out my.out > checktests.diffs cat checktests.diffs libtest.a: $(LHDRS) $(LOBJS) rm -f libtest.a ar r libtest.a $(LOBJS) $(RANLIB) libtest.a #test0: test0.h test.hello.o test.bye test.bye2 test.shell test0: test0.h test.bye test.bye2 test.shell $(GXX) test.hello.o $(GXXLDFLAGS) -o test0 test.hello.o: test0.h test.hello.cc $(GXX) -c $(GXXFLAGS) $(TFLAGS) test.hello.cc -o test.hello.o test.bye: test0.h test.bye.cc $(GXX) -c $(GXXFLAGS) test.bye.cc -o test.bye test.bye2: test0.h test.bye2.cc $(GXX) -c $(GXXFLAGS) test.bye2.cc -o test.bye2 test.shell: test0.h test.shell.cc $(GXX) -c $(GXXFLAGS) test.shell.cc -o test.shell tFile: tFile.o $(GXX) tFile.o -o tFile $(GXXLDFLAGS) tObstack: tObstack.o $(GXX) tObstack.o -o tObstack $(GXXLDFLAGS) tString: tString.o $(GXX) tString.o -o tString $(GXXLDFLAGS) tInteger: tInteger.o $(GXX) tInteger.o -o tInteger $(GXXLDFLAGS) twrapper: twrapper.o $(GXX) twrapper.o -o twrapper $(GXXLDFLAGS) tgwrapper: tgwrapper.o $(GXX) tgwrapper.o -o tgwrapper $(GXXLDFLAGS) tRational: tRational.o $(GXX) tRational.o -o tRational $(GXXLDFLAGS) tComplex: tComplex.o $(GXX) tComplex.o -o tComplex $(GXXLDFLAGS) tBitSet: tBitSet.o $(GXX) tBitSet.o -o tBitSet $(GXXLDFLAGS) tBitString: tBitString.o $(GXX) tBitString.o -o tBitString $(GXXLDFLAGS) tRandom: tRandom.o $(GXX) tRandom.o -o tRandom $(GXXLDFLAGS) tFix: tFix.o $(GXX) tFix.o -o tFix $(GXXLDFLAGS) tFix16: tFix16.o $(GXX) tFix16.o -o tFix16 $(GXXLDFLAGS) tFix24: tFix24.o $(GXX) tFix24.o -o tFix24 $(GXXLDFLAGS) tCurses: tCurses.o $(GXX) tCurses.o -o tCurses -lg++ -lcurses -ltermcap $(GXXLDFLAGS) tGetOpt: tGetOpt.o $(GXX) tGetOpt.o -o tGetOpt $(GXXLDFLAGS) tList: libtest.a tList.o $(GXX) tList.o -o tList libtest.a $(GXXLDFLAGS) tPlex: libtest.a tPlex.o $(GXX) tPlex.o -o tPlex libtest.a $(GXXLDFLAGS) tLList: libtest.a tLList.o $(GXX) tLList.o -o tLList libtest.a $(GXXLDFLAGS) tVec: libtest.a tVec.o $(GXX) tVec.o -o tVec libtest.a $(GXXLDFLAGS) tStack: libtest.a tStack.o $(GXX) tStack.o -o tStack libtest.a $(GXXLDFLAGS) tQueue: libtest.a tQueue.o $(GXX) tQueue.o -o tQueue libtest.a $(GXXLDFLAGS) tDeque: libtest.a tDeque.o $(GXX) tDeque.o -o tDeque libtest.a $(GXXLDFLAGS) tPQ: libtest.a tPQ.o $(GXX) tPQ.o -o tPQ libtest.a $(GXXLDFLAGS) tSet: libtest.a tSet.o $(GXX) tSet.o -o tSet libtest.a $(GXXLDFLAGS) tBag: libtest.a tBag.o $(GXX) tBag.o -o tBag libtest.a $(GXXLDFLAGS) tMap: libtest.a tMap.o $(GXX) tMap.o -o tMap libtest.a $(GXXLDFLAGS) idefs.h: $(GENCLASS) int val defs i iSet.cc : $(GENCLASS) int val Set i iXPSet.cc : $(GENCLASS) int val XPSet i iOXPSet.cc : $(GENCLASS) int val OXPSet i iSLSet.cc : $(GENCLASS) int val SLSet i iOSLSet.cc : $(GENCLASS) int val OSLSet i iBSTSet.cc : $(GENCLASS) int val BSTSet i iAVLSet.cc : $(GENCLASS) int val AVLSet i iSplaySet.cc : $(GENCLASS) int val SplaySet i iVHSet.cc : $(GENCLASS) int val VHSet i iVOHSet.cc : $(GENCLASS) int val VOHSet i iCHSet.cc : $(GENCLASS) int val CHSet i iBag.cc : $(GENCLASS) int val Bag i iXPBag.cc : $(GENCLASS) int val XPBag i iOXPBag.cc : $(GENCLASS) int val OXPBag i iSLBag.cc : $(GENCLASS) int val SLBag i iOSLBag.cc : $(GENCLASS) int val OSLBag i iSplayBag.cc : $(GENCLASS) int val SplayBag i iVHBag.cc : $(GENCLASS) int val VHBag i iCHBag.cc : $(GENCLASS) int val CHBag i iMap.cc : $(GENCLASS) -2 int val int val Map i iVHMap.cc : $(GENCLASS) -2 int val int val VHMap i iCHMap.cc : $(GENCLASS) -2 int val int val CHMap i iSplayMap.cc : $(GENCLASS) -2 int val int val SplayMap i iAVLMap.cc : $(GENCLASS) -2 int val int val AVLMap i iRAVLMap.cc : $(GENCLASS) -2 int val int val RAVLMap i iPQ.cc: $(GENCLASS) int val PQ i iPHPQ.cc: $(GENCLASS) int val PHPQ i iSplayPQ.cc: $(GENCLASS) int val SplayPQ i iXPPQ.cc: $(GENCLASS) int val XPPQ i iStack.h: $(GENCLASS) int val Stack i iQueue.h: $(GENCLASS) int val Queue i iDeque.h: $(GENCLASS) int val Deque i iSLStack.h: $(GENCLASS) int val SLStack i iSLQueue.h: $(GENCLASS) int val SLQueue i iDLDeque.h: $(GENCLASS) int val DLDeque i iList.cc: $(GENCLASS) int val List i iPlex.cc: $(GENCLASS) int val Plex i iFPlex.cc: $(GENCLASS) int val FPlex i iXPlex.cc: $(GENCLASS) int val XPlex i iMPlex.cc: $(GENCLASS) int val MPlex i iRPlex.cc: $(GENCLASS) int val RPlex i iFPStack.h: $(GENCLASS) int val FPStack i iXPStack.h: $(GENCLASS) int val XPStack i iFPQueue.h: $(GENCLASS) int val FPQueue i iXPQueue.h: $(GENCLASS) int val XPQueue i iXPDeque.h: $(GENCLASS) int val XPDeque i iSLList.cc: $(GENCLASS) int val SLList i iDLList.cc: $(GENCLASS) int val DLList i iVec.cc: $(GENCLASS) int val Vec i iAVec.cc: $(GENCLASS) int val AVec i iVStack.cc: $(GENCLASS) int val VStack i iVQueue.cc: $(GENCLASS) int val VQueue i relink: (rm -f $(TOUTS); make tests) clean: rm -f *.o core test.bye test.bye2 test.shell libtest.a $(TOUTS) $(GENCLASS) rm -f plot.out ffile streamfile i*.cc i*.h C++.hack* my.out checktests.diffs clean-executables: -rm -f core test.bye test.bye2 test.shell libtest.a $(TOUTS) # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. iAVLMap.o : iAVLMap.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iAVLMap.h iMap.h \ $(SRCIDIR)/Pix.h idefs.h iAVLSet.o : iAVLSet.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iAVLSet.h iSet.h \ $(SRCIDIR)/Pix.h idefs.h iAVec.o : iAVec.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iAVec.h iVec.h iBSTSet.o : iBSTSet.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iBSTSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h iBag.o : iBag.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h iBag.h $(SRCIDIR)/Pix.h \ idefs.h iCHBag.o : iCHBag.cc iCHBag.h iBag.h $(SRCIDIR)/Pix.h idefs.h iCHMap.o : iCHMap.cc iCHMap.h iMap.h $(SRCIDIR)/Pix.h idefs.h iCHSet.o : iCHSet.cc iCHSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h iDLList.o : iDLList.cc $(SRCIDIR)/values.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/streambuf.h \ iDLList.h $(SRCIDIR)/Pix.h idefs.h iFPlex.o : iFPlex.cc iFPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Pix.h idefs.h iList.o : iList.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h iList.h $(SRCIDIR)/Pix.h iMPlex.o : iMPlex.cc iMPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Pix.h idefs.h iMap.o : iMap.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h iMap.h $(SRCIDIR)/Pix.h \ idefs.h iOSLBag.o : iOSLBag.cc iOSLBag.h iBag.h $(SRCIDIR)/Pix.h \ idefs.h iSLList.h iOSLSet.o : iOSLSet.cc iOSLSet.h iSet.h $(SRCIDIR)/Pix.h \ idefs.h iSLList.h iOXPBag.o : iOXPBag.cc iOXPBag.h iBag.h $(SRCIDIR)/Pix.h \ idefs.h iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h iOXPSet.o : iOXPSet.cc iOXPSet.h iSet.h $(SRCIDIR)/Pix.h \ idefs.h iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h iPHPQ.o : iPHPQ.cc $(SRCIDIR)/values.h iPHPQ.h iPQ.h \ $(SRCIDIR)/Pix.h idefs.h iPQ.o : iPQ.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h iPQ.h $(SRCIDIR)/Pix.h \ idefs.h iPlex.o : iPlex.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iPlex.h $(SRCIDIR)/Pix.h idefs.h iRAVLMap.o : iRAVLMap.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iRAVLMap.h iMap.h \ $(SRCIDIR)/Pix.h idefs.h iRPlex.o : iRPlex.cc iRPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Pix.h idefs.h iSLBag.o : iSLBag.cc iSLBag.h iBag.h $(SRCIDIR)/Pix.h idefs.h \ iSLList.h iSLList.o : iSLList.cc $(SRCIDIR)/values.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/streambuf.h \ iSLList.h $(SRCIDIR)/Pix.h idefs.h iSLSet.o : iSLSet.cc iSLSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h \ iSLList.h iSet.o : iSet.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h iSet.h $(SRCIDIR)/Pix.h \ idefs.h iSplayBag.o : iSplayBag.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iSplayBag.h iBag.h \ $(SRCIDIR)/Pix.h idefs.h iSplayMap.o : iSplayMap.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iSplayMap.h iMap.h \ $(SRCIDIR)/Pix.h idefs.h iSplayPQ.o : iSplayPQ.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iSplayPQ.h iPQ.h \ $(SRCIDIR)/Pix.h idefs.h iSplaySet.o : iSplaySet.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iSplaySet.h iSet.h \ $(SRCIDIR)/Pix.h idefs.h iVHBag.o : iVHBag.cc iVHBag.h iBag.h $(SRCIDIR)/Pix.h idefs.h iVHMap.o : iVHMap.cc iVHMap.h iMap.h $(SRCIDIR)/Pix.h idefs.h iVHSet.o : iVHSet.cc iVHSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h iVOHSet.o : iVOHSet.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iVOHSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h iVQueue.o : iVQueue.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iVQueue.h iQueue.h idefs.h iVStack.o : iVStack.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iVStack.h iStack.h idefs.h iVec.o : iVec.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iVec.h iXPBag.o : iXPBag.cc iXPBag.h iBag.h $(SRCIDIR)/Pix.h idefs.h \ iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h iXPPQ.o : iXPPQ.cc iXPPQ.h iPQ.h $(SRCIDIR)/Pix.h idefs.h \ iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h iXPSet.o : iXPSet.cc iXPSet.h iSet.h $(SRCIDIR)/Pix.h idefs.h \ iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h iXPlex.o : iXPlex.cc iXPlex.h iPlex.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Pix.h idefs.h tBag.o : tBag.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iBag.h $(SRCIDIR)/Pix.h \ idefs.h $(SRCIDIR)/MLCG.h $(SRCIDIR)/RNG.h \ iXPBag.h iXPlex.h iPlex.h iSLBag.h iSLList.h iVHBag.h iCHBag.h iOXPBag.h \ iOSLBag.h iSplayBag.h tBitSet.o : tBitSet.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/BitSet.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h tBitString.o : tBitString.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/BitString.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h tComplex.o : tComplex.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/Complex.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h tCurses.o : tCurses.cc $(SRCIDIR)/CursesWindow.h \ $(SRCIDIR)/curses.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h tDeque.o : tDeque.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iDeque.h idefs.h iXPDeque.h iXPlex.h \ iPlex.h $(SRCIDIR)/Pix.h iDLDeque.h iDLList.h tFile.o : tFile.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/SFile.h $(SRCIDIR)/PlotFile.h \ $(SRCIDIR)/assert.h tFix.o : tFix.cc $(SRCIDIR)/Fix.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Integer.h tFix16.o : tFix16.cc $(SRCIDIR)/Fix16.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h tFix24.o : tFix24.cc $(SRCIDIR)/Fix24.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h tGetOpt.o : tGetOpt.cc $(SRCIDIR)/GetOpt.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h tInteger.o : tInteger.cc $(SRCIDIR)/Integer.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/assert.h tLList.o : tLList.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h iSLList.h \ $(SRCIDIR)/Pix.h idefs.h iDLList.h tList.o : tList.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h iList.h $(SRCIDIR)/Pix.h \ $(SRCIDIR)/MLCG.h $(SRCIDIR)/RNG.h tMap.o : tMap.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iMap.h $(SRCIDIR)/Pix.h \ idefs.h $(SRCIDIR)/MLCG.h $(SRCIDIR)/RNG.h \ iSplayMap.h iVHMap.h iCHMap.h iAVLMap.h iRAVLMap.h tObstack.o : tObstack.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Obstack.h \ $(SRCIDIR)/ctype.h tPQ.o : tPQ.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iPQ.h $(SRCIDIR)/Pix.h \ idefs.h $(SRCIDIR)/MLCG.h $(SRCIDIR)/RNG.h \ iXPPQ.h iXPlex.h iPlex.h iPHPQ.h iSplayPQ.h tPlex.o : tPlex.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iPlex.h $(SRCIDIR)/Pix.h \ idefs.h iFPlex.h iXPlex.h iMPlex.h iRPlex.h tQueue.o : tQueue.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iQueue.h idefs.h iXPQueue.h iXPlex.h \ iPlex.h $(SRCIDIR)/Pix.h iVQueue.h iSLQueue.h iSLList.h tRandom.o : tRandom.cc $(SRCIDIR)/assert.h \ $(SRCIDIR)/ACG.h $(SRCIDIR)/RNG.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/MLCG.h $(SRCIDIR)/SampleStatistic.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/SampleHistogram.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Binomial.h \ $(SRCIDIR)/Random.h $(SRCIDIR)/Erlang.h \ $(SRCIDIR)/Geometric.h \ $(SRCIDIR)/HyperGeometric.h \ $(SRCIDIR)/NegativeExpntl.h $(SRCIDIR)/Normal.h \ $(SRCIDIR)/LogNormal.h $(SRCIDIR)/Poisson.h \ $(SRCIDIR)/Uniform.h \ $(SRCIDIR)/DiscreteUniform.h \ $(SRCIDIR)/Weibull.h tRational.o : tRational.cc $(SRCIDIR)/Rational.h \ $(SRCIDIR)/Integer.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h tSet.o : tSet.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iSet.h $(SRCIDIR)/Pix.h \ idefs.h $(SRCIDIR)/MLCG.h $(SRCIDIR)/RNG.h \ iXPSet.h iXPlex.h iPlex.h iSLSet.h iSLList.h iVHSet.h iVOHSet.h iCHSet.h \ iOXPSet.h iOSLSet.h iBSTSet.h iAVLSet.h iSplaySet.h tStack.o : tStack.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/assert.h iStack.h idefs.h iXPStack.h iXPlex.h \ iPlex.h $(SRCIDIR)/Pix.h iVStack.h iSLStack.h iSLList.h tString.o : tString.cc $(SRCIDIR)/String.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/assert.h tVec.o : tVec.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ iVec.h iAVec.h $(SRCIDIR)/MLCG.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h test.bye.o : test.bye.cc $(SRCIDIR)/Incremental.h test0.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h test.bye2.o : test.bye2.cc $(SRCIDIR)/Incremental.h test0.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h test.hello.o : test.hello.cc test0.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/sys/file.h $(SRCIDIR)/sys/types.h test.shell.o : test.shell.cc $(SRCIDIR)/Incremental.h test0.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h tgwrapper.o : tgwrapper.cc $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Integer.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h twrapper.o : twrapper.cc $(SRCIDIR)/Integer.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY per.cc $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/Integer.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIlibg++/tests/tComplex.cc 644 473 0 7014 4677700031 10400 /* a test file for Complex */ #include #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } #include // to test near-equality const double eps = 0.000001; static void close_enough(const Complex& a, const Complex& b) { assert(abs(real(a) - real(b)) < eps && abs(imag(a) - imag(b)) < eps); } void test3(Complex& a, Complex& b, Complex& c) { close_enough(-(-a) , a); close_enough((a + b) , (b + a)); close_enough((a + (-b)) , (a - b)); close_enough((a * b) , (b * a)); close_enough((a * (-b)) , -(a * b)); close_enough((a / (-b)) , -(a / b)); close_enough((a - b) , -(b - a)); close_enough((a + (b + c)) , ((a + b) + c)); close_enough((a * (b * c)) , ((a * b) * c)); close_enough((a * (b + c)) , ((a * b) + (a * c))); close_enough(((a - b) + b) , a); close_enough(((a + b) - b) , a); close_enough(((a * b) / b) , a); close_enough(((a / b) * b) , a); Complex x = a; x *= b; close_enough(x , (a * b)); x += c; close_enough(x , ((a * b) + c)); x -= a; close_enough(x , (((a * b) + c) - a)); x /= b; close_enough(x , ((((a * b) + c) - a) / b)); } main() { Complex one = 1.0; Complex i (0.0, 1.0); Complex neg_one = -1.0; cout << "Complex one = " << one << "\n"; cout << "i = " << i << "\n"; cout << "neg_one = " << neg_one << "\n"; cout << "sqrt(neg_one) = " << sqrt(neg_one) << "\n"; Complex a (2.0, 3.0); Complex b (4.0, 5.0); cout << "a = " << a << "\n"; cout << "b = " << b << "\n"; cout << "a + one = " << (a + one) << "\n"; (close_enough((a+one), Complex(3.0, 3.0))); cout << "a - one = " << (a - one) << "\n"; (close_enough((a-one), Complex(1.0, 3.0))); cout << "a * one = " << (a * one) << "\n"; (close_enough((a*one), a)); cout << "a / one = " << (a / one) << "\n"; (close_enough((a/one), a)); cout << "a + b = " << (a + b) << "\n"; (close_enough((a+b), Complex(6.0, 8.0))); cout << "a - b = " << (a - b) << "\n"; (close_enough((a-b), Complex(-2.0, -2.0))); cout << "a * b = " << (a * b) << "\n"; (close_enough((a*b), Complex(-7.0, 22.0))); cout << "a / b = " << (a / b) << "\n"; (close_enough((a/b), Complex(0.5609760976, 0.0487804878))); Complex c; c = a; cout << "c = a; c += b = " << (c += b) << "\n"; c = a; cout << "c = a; c -= b = " << (c -= b) << "\n"; c = a; cout << "c = a; c *= b = " << (c *= b) << "\n"; c = a; cout << "c = a; c /= b = " << (c /= b) << "\n"; cout << "-a = " << (-a) << "\n"; cout << "real(a) = " << real(a) << "\n"; assert(real(a) == 2.0); cout << "imag(a) = " << imag(a) << "\n"; assert(imag(a) == 3.0); cout << "conj(a) = " << conj(a) << "\n"; assert(conj(a) == Complex(2.0, -3.0)); cout << "norm(a) = " << norm(a) << "\n"; assert(norm(a) == 13.0); cout << "abs(a) = " << abs(a) << "\n"; cout << "arg(a) = " << arg(a) << "\n"; cout << "cos(a) = " << cos(a) << "\n"; cout << "sin(a) = " << sin(a) << "\n"; cout << "cosh(a) = " << cosh(a) << "\n"; cout << "sinh(a) = " << sinh(a) << "\n"; cout << "log(a) = " << log(a) << "\n"; cout << "exp(a) = " << exp(a) << "\n"; cout << "sqrt(a) = " << sqrt(a) << "\n"; cout << "pow(a, 2) = " << pow(a, 2) << "\n"; cout << "pow(a, b) = " << pow(a, b) << "\n"; Complex d (10, 20); Complex e = pow(a, 2); test3(one, one, one); test3(a, a, a); test3(a, b, d); test3(e, i, b); test3(d, d, i); cout << "enter a Complex number in form (a, b) or (a) or a: "; cin >> c; cout << "number = " << c << "\n"; cout << "\nEnd of test\n"; } cout << "log(a) = " << log(a) << "\n"; cout << "exp(a) = " << exp(a) << "\n"; cout << "sqrt(a) = " << sqrt(a) << "\n"; cout << "pow(a, 2) = " << pow(a, 2) << "\n"; cout << "pow(a, b) = " << pow(a, b) << "\n"; Complex d (10, 20); Complex e = pow(a, 2); test3(one, one, one); test3(a, a, a); test3(a, b, d); test3(e, i, b); test3(d, d, i); cout << "enter a Complex number in form (a, b) or (a) or a: "; cin >> c; cout << "number = " << c << "\n"; cout << "\nEnd oflibg++/tests/tObstack.cc 644 473 0 3053 4677700031 10356 // This may look like C code, but it is really -*- C++ -*- /* a little test of Obstacks Thu Feb 18 11:16:28 1988 Doug Lea (dl at rocky.oswego.edu) */ #include #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } #include #include #include #include main() { char* s[10000]; int n = 0; int got_one = 0; Obstack os; char c; s[n++] = os.copy("\nunique words:"); assert(os.OK()); assert(os.contains(s[0])); cout << "enter anything at all, end with an EOF(^D)\n"; while (cin.good() && n < 10000) { if (cin.get(c) && isalnum(c)) { got_one = 1; os.grow(c); } else if (got_one) { char* current = os.finish(0); for (int i = 0; i < n; ++i) // stupid, but this is only a test. { if (strcmp(s[i], current) == 0) { os.free(current); current = 0; break; } } if (current != 0) s[n++] = current; got_one = 0; } } assert(os.OK()); cout << s[0] << "\n"; for (int i = n - 1; i > 0; -- i) { assert(os.contains(s[i])); cout << s[i] << "\n"; os.free(s[i]); } assert(os.OK()); assert(os.contains(s[0])); cout << "\n\nObstack vars:\n"; cout << "alignment_mask = " << os.alignment_mask() << "\n"; cout << "chunk_size = " << os.chunk_size() << "\n"; cout << "size = " << os.size() << "\n"; cout << "room = " << os.room() << "\n"; cout << "\nend of test\n"; } ; got_one = 0; } } assert(os.OK()); cout << s[0] << "\n"; for (int i = n - 1; i > 0; -- i) { assert(os.contains(s[i])); cout << s[i] << "\n"; os.free(s[i]); } assert(os.OK()); assert(os.contains(s[0])); cout << "\n\nObstack vars:\n"; cout << "alignment_mask = " << os.alignment_mask() << "\n"; cout << "chunk_size = " << os.chunk_size() << "\n"; cout << "size = " << os.size() << "\n"; cout << "room = " << os.room() libg++/tests/tString.cc 644 473 0 20200 4677700031 10247 // This may look like C code, but it is really -*- C++ -*- /* A test file for Strings */ #include #include #include // can't nicely echo assertions because they contain quotes #define tassert(ex) {if (!(ex)) \ { cerr << "failed assertion at " << __LINE__ << "\n"; \ abort(); } } String X = "Hello"; String Y = "world"; String N = "123"; String c; char* s = ","; Regex r = "e[a-z]*o"; void decltest() { String x; cout << "an empty String:" << x << "\n"; assert(x.OK()); assert(x == ""); String y = "Hello"; cout << "A string initialized to Hello:" << y << "\n"; assert(y.OK()); assert(y == "Hello"); String a = y; cout << "A string initialized to previous string:" << a << "\n"; assert(a.OK()); assert(a == "Hello"); assert(a == y); String b (a.at(1, 2)); cout << "A string initialized to previous string.at(1, 2):" << b << "\n"; assert(b.OK()); assert(b == "el"); char ch = '@'; String z(ch); cout << "A string initialized to @:" << z << "\n"; assert(z.OK()); assert(z == "@"); String n = dec(20); cout << "A string initialized to dec(20):" << n << "\n"; assert(n.OK()); assert(n == "20"); int i = atoi(n); double f = atof(n); cout << "n = " << n << " atoi(n) = " << i << " atof(n) = " << f << "\n"; assert(i == 20); assert(f == 20); assert(X.OK()); assert(Y.OK()); assert(x.OK()); assert(y.OK()); assert(z.OK()); assert(n.OK()); assert(r.OK()); } void cattest() { String x = X; String y = Y; String z = x + y; cout << "z = x + y = " << z << "\n"; assert(x.OK()); assert(y.OK()); assert(z.OK()); assert(z == "Helloworld"); x += y; cout << "x += y; x = " << x << "\n"; assert(x.OK()); assert(y.OK()); assert(x == "Helloworld"); y = Y; x = X; y.prepend(x); cout << "y.prepend(x); y = " << y << "\n"; assert(y == "Helloworld"); y = Y; x = X; cat(x, y, x, x); cout << "cat(x, y, x, x); x = " << x << "\n"; assert(x == "HelloworldHello"); y = Y; x = X; cat(y, x, x, x); cout << "cat(y, x, x, x); x = " << x << "\n"; assert(x == "worldHelloHello"); x = X; y = Y; z = x + s + ' ' + y.at("w") + y.after("w") + "."; cout << "z = x + s + + y.at(w) + y.after(w) + . = " << z << "\n"; assert(z.OK()); assert(z == "Hello, world."); } void comparetest() { String x = X; String y = Y; String n = N; String z = x + y; assert(x != y); assert(x == "Hello"); assert(x != z.at(0, 4)); assert (x < y); assert(!(x >= z.at(0, 6))); assert(x.contains("He")); assert (z.contains(x)); assert(x.contains(r)); assert(!(x.matches(r))); assert(x.matches(RXalpha)); assert(!(n.matches(RXalpha))); assert(n.matches(RXint)); assert(n.matches(RXdouble)); assert(x.index("lo") == 3); assert(x.index("l", 2) == 2); assert(x.index("l", -1) == 3); assert(x.index(r) == 1); assert(x.index(r, -2) == 1); assert(x.contains("el", 1)); assert(x.contains("el")); assert(common_prefix(x, "Help") == "Hel"); assert(common_suffix(x, "to") == "o"); assert(fcompare(x, "hELlo") == 0); assert(fcompare(x, "hElp") < 0); } void substrtest() { String x = X; char ch = x[0]; cout << "ch = x[0] = " << ch << "\n"; assert(ch == 'H'); String z = x.at(2, 3); cout << "z = x.at(2, 3) = " << z << "\n"; assert(z.OK()); assert(z == "llo"); x.at(2, 2) = "r"; cout << "x.at(2, 2) = r; x = " << x << "\n"; assert(x.OK()); assert(x.at(2,2).OK()); assert(x == "Hero"); x = X; x.at(0, 1) = "j"; cout << "x.at(0, 1) = j; x = " << x << "\n"; assert(x.OK()); assert(x == "jello"); x = X; x.at("He") = "je"; cout << "x.at(He) = je; x = " << x << "\n"; assert(x.OK()); assert(x == "jello"); x = X; x.at("l", -1) = "i"; cout << "x.at(l, -1) = i; x = " << x << "\n"; assert(x.OK()); assert(x == "Helio"); x = X; z = x.at(r); cout << "z = x.at(r) = " << z << "\n"; assert(z.OK()); assert(z == "ello"); z = x.before("o"); cout << "z = x.before(o) = " << z << "\n"; assert(z.OK()); assert(z == "Hell"); x.before("ll") = "Bri"; cout << "x.before(ll) = Bri; x = " << x << "\n"; assert(x.OK()); assert(x == "Brillo"); x = X; z = x.before(2); cout << "z = x.before(2) = " << z << "\n"; assert(z.OK()); assert(z == "He"); z = x.after("Hel"); cout << "z = x.after(Hel) = " << z << "\n"; assert(z.OK()); assert(z == "lo"); x.after("Hel") = "p"; cout << "x.after(Hel) = p; x = " << x << "\n"; assert(x.OK()); assert(x == "Help"); x = X; z = x.after(3); cout << "z = x.after(3) = " << z << "\n"; assert(z.OK()); assert(z == "o"); z = " a bc"; z = z.after(RXwhite); cout << "z = a bc; z = z.after(RXwhite); z =" << z << "\n"; assert(z.OK()); assert(z == "a bc"); } void utiltest() { String x = X; int matches = x.gsub("l", "ll"); cout << "x.gsub(l, ll); x = " << x << "\n"; assert(x.OK()); assert(matches == 2); assert(x == "Hellllo"); x = X; assert(x.OK()); matches = x.gsub(r, "ello should have been replaced by this string"); assert(x.OK()); cout << "x.gsub(r, ...); x = " << x << "\n"; assert(x.OK()); assert(matches == 1); assert(x == "Hello should have been replaced by this string"); matches = x.gsub(RXwhite, "#"); cout << "x.gsub(RXwhite, #); x = " << x << "\n"; assert(matches == 7); assert(x.OK()); String z = X + Y; z.del("loworl"); cout << "z = x+y; z.del(loworl); z = " << z << "\n"; assert(z.OK()); assert(z == "Held"); x = X; z = reverse(x); cout << "reverse(x) = " << z << "\n"; assert(z.OK()); assert(z == "olleH"); x.reverse(); cout << "x.reverse() = " << x << "\n"; assert(x.OK()); assert(x == z); x = X; z = upcase(x); cout << "upcase(x) = " << z << "\n"; assert(z.OK()); assert(z == "HELLO"); z = downcase(x); cout << "downcase(x) = " << z << "\n"; assert(z.OK()); assert(z == "hello"); z = capitalize(x); cout << "capitalize(x) = " << z << "\n"; assert(z.OK()); assert(z == "Hello"); z = replicate('*', 10); cout << "z = replicate(*, 10) = " << z << "\n"; assert(z.OK()); assert(z == "**********"); assert(z.length() == 10); } void splittest() { String z = "This string\thas\nfive words"; cout << "z = " << z << "\n"; String w[10]; int nw = split(z, w, 10, RXwhite); assert(nw == 5); cout << "from split(z, RXwhite, w, 10), n words = " << nw << ":\n"; for (int i = 0; i < nw; ++i) { assert(w[i].OK()); cout << w[i] << "\n"; } assert(w[0] == "This"); assert(w[1] == "string"); assert(w[2] == "has"); assert(w[3] == "five"); assert(w[4] == "words"); assert(w[5] == 0); z = join(w, nw, "/"); cout << "z = join(w, nw, /); z =" << z << "\n"; assert(z.OK()); assert(z == "This/string/has/five/words"); } void iotest() { String z; cout << "enter a word:"; cin >> z; cout << "word =" << z << " "; cout << "length = " << z.length() << "\n"; } void identitytest(String a, String b) { String x = a; String y = b; x += b; y.prepend(a); assert((a + b) == x); assert((a + b) == y); assert(x == y); assert(x.after(a) == b); assert(x.before(b, -1) == a); assert(x.from(a) == x); assert(x.through(b, -1) == x); assert(x.at(a) == a); assert(x.at(b) == b); assert(reverse(x) == reverse(b) + reverse(a)); assert((a + b + a) == (a + (b + a))); x.del(b, -1); assert(x == a); y.before(b, -1) = b; assert(y == (b + b)); y.at(b) = a; assert(y == (a + b)); x = a + reverse(a); for (int i = 0; i < 7; ++i) { y = x; x += x; assert(x.OK()); assert(x == reverse(x)); assert(x.index(y) == 0); assert(x.index(y, -1) == x.length() / 2); } } void freqtest() { String x = "Hello World"; SubString y = x.at(0,5); assert(x.freq('l') == 3); // char assert(x.freq("lo") == 1); // char* assert(x.freq(x) == 1); // String assert(x.freq(y) == 1); // SubString } main() { decltest(); cattest(); comparetest(); substrtest(); utiltest(); splittest(); freqtest(); identitytest(X, X); identitytest(X, Y); identitytest(X+Y+N+X+Y+N, "A string that will be used in identitytest but is otherwise just another useless string."); iotest(); cout << "\nEnd of test\n"; } lo World"; SubString y = x.at(0,5); assert(x.freq('l') == 3); // char assert(x.freq("lo") == 1); // char* assert(x.freq(x) == 1); // String assert(x.freq(y) == 1); // SubString } main() { decltest(); cattest(); comparetest(); substrtest(); utiltest(); splittest(); freqtest(); identitytest(X, X); identitytest(X, Y); identitytest(X+Y+N+X+Y+N, "A string libg++/tests/tDeque.cc 644 473 0 5557 4677700031 10046 /* test of Deques */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #include "iDeque.h" #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } int SIZE; void print(intDeque& a) { int maxprint = 20; cout << "["; int k = 0; while (!a.empty() && k++ < maxprint) cout << a.deq() << " "; if (k == maxprint) cout << "]\n"; else { while (!a.empty()) a.del_front(); cout << "...]\n"; } assert(a.empty()); } #include "iXPDeque.h" void XPtest () { intXPDeque d(SIZE); assert(d.OK()); for (int i = 0; i < SIZE; ++i) { if (i % 2 == 0) d.enq(i); else d.push(i); } assert(d.length() == SIZE); assert(d.front() == (SIZE-1)); assert(d.rear() == (SIZE-2)); assert(!d.full()); intXPDeque d1(SIZE/2); for (i = (SIZE-1); i >= 0; --i) { int x; if (i % 2 == 0) { x = d.rear(); d.del_rear(); } else { x = d.front(); d.del_front(); } d1.enq(x); } assert(d.empty()); assert(d1.length() == SIZE); assert(d1.front() == (SIZE-1)); assert(d1.rear() == 0); assert(d.OK()); assert(d1.OK()); intXPDeque d2 (d1); assert(d2.length() == SIZE); assert(d2.front() == (SIZE-1)); assert(d2.OK()); d1.clear(); assert(d1.empty()); d1 = d2; assert(d1.length() == SIZE); assert(d1.front() == (SIZE-1)); cout << "d1:"; print(d1); assert(d.OK()); assert(d1.OK()); assert(d2.OK()); } #include "iDLDeque.h" void DLtest () { intDLDeque d; assert(d.OK()); for (int i = 0; i < SIZE; ++i) { if (i % 2 == 0) d.enq(i); else d.push(i); } assert(d.length() == SIZE); assert(d.front() == (SIZE-1)); assert(d.rear() == (SIZE-2)); assert(!d.full()); intDLDeque d1; for (i = (SIZE-1); i >= 0; --i) { int x; if (i % 2 == 0) { x = d.rear(); d.del_rear(); } else { x = d.front(); d.del_front(); } d1.enq(x); } assert(d.empty()); assert(d1.length() == SIZE); assert(d1.front() == (SIZE-1)); assert(d1.rear() == 0); assert(d.OK()); assert(d1.OK()); intDLDeque d2 (d1); assert(d2.length() == SIZE); assert(d2.front() == (SIZE-1)); assert(d2.OK()); d1.clear(); assert(d1.empty()); d1 = d2; assert(d1.length() == SIZE); assert(d1.front() == (SIZE-1)); cout << "d1:"; print(d1); assert(d.OK()); assert(d1.OK()); assert(d2.OK()); } main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; start_timer(); cout << "XP deques:\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "DL deques:\n"; DLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; cout << "\nEnd of test\n"; } nt() == (SIZE-1)); cout << "d1:"; print(d1); assert(d.OK()); assert(d1.OK()); assert(d2.OK()); } main(int argv, char** argc) { if (alibg++/tests/tInteger.cc 644 473 0 23222 4677700032 10406 /* a test file for Integer class */ #include #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } Integer factorial(Integer n) { Integer f; if (n < 0) f = 0; else { f = 1; while (n > 0) { f *= n; --n; } } return f; } Integer fibonacci(long n) { Integer f; if (n <= 0) f = 0; else { f = 1; Integer prev = 0; Integer tmp; while (n > 1) { tmp = f; f += prev; prev = tmp; --n; } } return f; } void identitytest(Integer& a, Integer& b, Integer& c) { assert( -(-a) == a); assert( (a + b) == (b + a)); assert( (a + (-b)) == (a - b)); assert( (a * b) == (b * a)); assert( (a * (-b)) == -(a * b)); assert( (a / (-b)) == -(a / b)); assert( (a - b) == -(b - a)); assert( (a + (b + c)) == ((a + b) + c)); assert( (a * (b * c)) == ((a * b) * c)); assert( (a * (b + c)) == ((a * b) + (a * c))); assert( ((a - b) + b) == a); assert( ((a + b) - b) == a); assert( ((a * b) / b) == a); assert( ((a * b) % b) == 0); assert( (b * (a / b) + (a % b)) == a); assert( ((a + b) % c) == ((a % c) + (b % c)) % c); } void utiltest(Integer& a) { assert(sqrt(sqr(a)) == a); assert(sqr(sqrt(a)) <= a); Integer x = 1; for (int i = 0; i < 10; ++i) { assert(pow(a, i) == x); x *= a; } setbit(x, 0); assert(testbit(x, 0)); assert(odd(x)); assert(!even(x)); clearbit(x, 0); clearbit(x, 1); assert(even(x)); assert(!odd(x)); assert(x % 4 == 0); } void bittest(Integer& a, Integer& b, Integer& c) { assert( (a | b) == (b | a)); assert( (a & b) == (b & a)); assert( (a ^ b) == (b ^ a)); assert( (a | (b | c)) == ((a | b) | c)); assert( (a & (b & c)) == ((a & b) & c)); assert( (a & (b | c)) == ((a & b) | (a & c))); assert( (a | (b & c)) == ((a | b) & (a | c))); assert( (a & (a | b)) == a); assert( (a | (a & b)) == a); } void accumtest(Integer& a, Integer& b, Integer& c) { Integer x = a; x *= b; assert(x == (a * b)); x += c; assert(x == ((a * b) + c)); x -= a; assert(x == (((a * b) + c) - a)); x /= b; assert(x == ((((a * b) + c) - a) / b)); x %= c; assert(x == (((((a * b) + c) - a) / b) % c)); x &= a; assert(x == ((((((a * b) + c) - a) / b) % c) & a)); x |= b; assert(x == (((((((a * b) + c) - a) / b) % c) & a) | b)); x ^= c; assert(x == ((((((((a * b) + c) - a) / b) % c) & a) | b) ^ c)); assert(x.OK()); } void longidentitytest(Integer& a, long b, long c) { assert( (a + b) == (b + a)); assert( (a + (-b)) == (a - b)); assert( (a * b) == (b * a)); assert( (a * (-b)) == -(a * b)); assert( (a / (-b)) == -(a / b)); assert( (a - b) == -(b - a)); assert( (a + (b + c)) == ((a + b) + c)); assert( (a * (b * c)) == ((a * b) * c)); assert( (a * (b + c)) == ((a * b) + (a * c))); assert( ((a - b) + b) == a); assert( ((a + b) - b) == a); assert( ((a * b) / b) == a); assert( ((a * b) % b) == 0); assert( (b * (a / b) + (a % b)) == a); assert( ((a + b) % c) == ((a % c) + (b % c)) % c); } void longbittest(Integer& a, long b, long c) { assert( (a | b) == (b | a)); assert( (a & b) == (b & a)); assert( (a ^ b) == (b ^ a)); assert( (a | (b | c)) == ((a | b) | c)); assert( (a & (b & c)) == ((a & b) & c)); assert( (a & (b | c)) == ((a & b) | (a & c))); assert( (a | (b & c)) == ((a | b) & (a | c))); assert( (a & (a | b)) == a); assert( (a | (a & b)) == a); } void longaccumtest(Integer& a, long b, long c) { Integer x = a; x *= b; assert(x == (a * b)); x += c; assert(x == ((a * b) + c)); x -= a; assert(x == (((a * b) + c) - a)); x /= b; assert(x == ((((a * b) + c) - a) / b)); x %= c; assert(x == (((((a * b) + c) - a) / b) % c)); x &= a; assert(x == ((((((a * b) + c) - a) / b) % c) & a)); x |= b; assert(x == (((((((a * b) + c) - a) / b) % c) & a) | b)); x ^= c; assert(x == ((((((((a * b) + c) - a) / b) % c) & a) | b) ^ c)); assert(x.OK()); } void anothertest() { Integer pow64 = Ipow(2, 64); cout << "pow64 = Ipow(2, 64) = " << pow64 << "\n"; assert(pow64.OK()); cout << "lg(pow64) = " << lg(pow64) << "\n"; assert(lg(pow64) == 64); for (int k = 0; k < 64; ++k) assert(testbit(pow64, k) == 0); assert(testbit(pow64, k) != 0); Integer s64 = 1; s64 <<= 64; cout << "s64 = 1 << 64 = " << s64 << "\n"; assert(s64.OK()); assert(s64 == pow64); assert(s64 >= pow64); assert(s64 <= pow64); assert(!(s64 != pow64)); assert(!(s64 > pow64)); assert(!(s64 < pow64)); Integer s32 = s64 >> 32; cout << "s32 = s64 >> 32 = " << s32 << "\n"; assert(s32.OK()); assert(lg(s32) == 32); assert(!(pow64 == s32)); assert(!(pow64 < s32)); assert(!(pow64 <= s32)); assert(pow64 != s32); assert(pow64 >= s32); assert(pow64 > s32); Integer comps64 = ~s64; cout << "comps64 = ~s64 = " << comps64 << "\n"; for (k = 0; k < 64; ++k) assert(testbit(comps64, k) == !testbit(s64, k)); Integer result = (comps64 & s32); cout << "comps64 & s32 = " << result << "\n"; assert(result.OK()); result = (comps64 | s32); cout << "comps64 | s32 = " << result << "\n"; assert(result.OK()); result = (comps64 ^ s32); cout << "comps64 ^ s32 = " << result << "\n"; assert(result.OK()); identitytest(s64, s32, comps64); bittest(s32, s64, comps64); accumtest(comps64, s32, pow64); utiltest(s32); longidentitytest(s64, 1000, 50); longbittest(s64, 12345, 67890); longaccumtest(s32, 100000, 1); } void iotest() { Integer result; cout << "\nenter an Integer: "; cin >> result; cout << "number = " << result << "\n"; assert(result.OK()); } void fibtest() { Integer fib50 = fibonacci(50); cout << "fib50 = fibonacci(50) = " << fib50 << "\n"; assert(fib50.OK()); Integer fib48 = fibonacci(48); cout << "fib48 = fibonacci(48) = " << fib48 << "\n"; assert(fib48.OK()); Integer result = fib48 + fib50; cout << "fib48 + fib50 = " << result << "\n"; result = fib48 - fib50; cout << "fib48 - fib50 = " << result << "\n"; result = fib48 * fib50; cout << "fib48 * fib50 = " << result << "\n"; result = fib48 / fib50; cout << "fib48 / fib50 = " << result << "\n"; result = fib48 % fib50; cout << "fib48 % fib50 = " << result << "\n"; result = gcd(fib50, fib48); cout << "gcd(fib50, fib48) = " << result << "\n"; result = sqrt(fib50); cout << "sqrt(fib50) = " << result << "\n"; identitytest(result, fib50, fib48); bittest(result, fib50, fib48); accumtest(result, fib50, fib48); utiltest(fib48); longidentitytest(fib50, 1000, 50); longaccumtest(fib48, 100000, 1); } void facttest(Integer& one, Integer& two) { Integer fact30(factorial(30)); cout << "fact30 = factorial(30) = " << fact30 << "\n"; assert(fact30.OK()); Integer fact28(factorial(28)); cout << "fact28 = factorial(28) = " << fact28 << "\n"; assert(fact28.OK()); assert(fact30 == fact28 * 870); Integer result = fact30 + fact28; cout << "fact30 + fact28 = " << result << "\n"; result = fact30 - fact28; cout << "fact30 - fact28 = " << result << "\n"; result = fact30 * fact28; cout << "fact30 * fact28 = " << result << "\n"; result = fact30 / fact28; cout << "fact30 / fact28 = " << result << "\n"; result = fact30 % fact28; cout << "fact30 % fact28 = " << result << "\n"; result = -fact30; cout << "-fact30 = " << result << "\n"; assert(abs(result) == fact30); cout << "lg(fact30) = " << lg(fact30) << "\n"; assert(lg(fact30) == 107); result = gcd(fact30, fact28); cout << "gcd(fact30, fact28) = " << result << "\n"; assert(result == fact28); result = sqrt(fact30); cout << "sqrt(fact30) = " << result << "\n"; Integer negfact31 = fact30 * -31; Integer posfact31 = abs(negfact31); assert(negfact31.OK()); assert(posfact31.OK()); cout << "negfact31 = " << negfact31 << "\n"; result = fact30 + negfact31; cout << "fact30 + negfact31 = " << result << "\n"; result = fact30 - negfact31; cout << "fact30 - negfact31 = " << result << "\n"; result = fact30 * negfact31; cout << "fact30 * negfact31 = " << result << "\n"; result = fact30 / negfact31; cout << "fact30 / negfact31 = " << result << "\n"; result = fact30 % negfact31; cout << "fact30 % negfact31 = " << result << "\n"; result = gcd(fact30, negfact31); cout << "gcd(fact30, negfact31) = " << result << "\n"; assert(result == fact30); identitytest(one, one, one); identitytest(one, one, one); identitytest(one, two, fact30); identitytest(fact30, posfact31, fact28); identitytest(fact30, negfact31, fact28); identitytest(negfact31, posfact31, fact28); bittest(one, one, one); bittest(one, one, one); bittest(one, two, fact30); bittest(fact30, posfact31, fact28); accumtest(one, one, one); accumtest(one, one, one); accumtest(one, two, fact30); accumtest(fact30, posfact31, fact28); utiltest(one); utiltest(fact30); utiltest(posfact31); longidentitytest(one, 1, 1); longidentitytest(one, 2, 3); longidentitytest(fact30, 3, -20); longidentitytest(fact30, 4, 20000); longidentitytest(negfact31, -100, 20000); longbittest(one, 1, 1); longbittest(one, 2, 3); longbittest(fact30, 4, 20000); longbittest(fact28, 1000, 50); longaccumtest(one, 1, 1); longaccumtest(one, 2, 3); longaccumtest(fact30, 4, 20000); longaccumtest(fact30, 1000, 50); longaccumtest(fact28, 10000000, 100000000); } main() { Integer one = 1; cout << "one = " << one << "\n"; assert(one.OK()); assert(one == 1); cout << "one + 1 = " << (one + 1) << "\n"; Integer two = 2; cout << "two = " << two << "\n"; assert(two.OK()); assert(two == 2); facttest(one, two); fibtest(); anothertest(); iotest(); cout << "\nEnd of test\n"; } ongaccumtest(one, 1, 1); longaccumtest(one, 2, 3); longaccumtest(fact30, 4, 20000); longaccumtest(fact30, 1000, 50); longaccumtest(fact28, 10000000, 100000000); } main() { Integer one = 1; cout << "one = " << one << "\n"; assert(one.OK()); assert(one == 1); cout << "one + 1 = " << (one + 1) << "\n"; Integer two = 2; cout << "two = " << two libg++/tests/tStack.cc 644 473 0 7003 4677700032 10035 /* test of stacks */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #include "iStack.h" #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } int SIZE; void print(intStack& a) { int maxprint = 20; cout << "["; int k = 0; while (!a.empty() && k++ < maxprint) cout << a.pop() << " "; if (k == maxprint) cout << "]\n"; else { while (!a.empty()) a.del_top(); cout << "...]\n"; } assert(a.empty()); } #include "iXPStack.h" void XPtest () { intXPStack s(SIZE/2); assert(s.OK()); for (int i = 0; i < SIZE; ++i) s.push(i); assert(s.length() == SIZE); assert(s.top() == (SIZE-1)); assert(!s.full()); intXPStack s1(SIZE*2); for (i = 0; i < SIZE; ++i) { int x = s.pop(); assert(x == (SIZE-1) - i); s1.push(x); } assert(s.empty()); assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s.OK()); assert(s1.OK()); intXPStack s2 (s1); assert(s2.length() == SIZE); assert(s2.top() == 0); assert(s2.OK()); s1.clear(); assert(s1.empty()); s1 = s2; assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s1.OK()); s1.del_top(); assert(s1.length() == (SIZE-1)); assert(s1.top() == 1); cout << "s1:"; print(s1); assert(s.OK()); assert(s1.OK()); assert(s2.OK()); } #include "iVStack.h" void Vtest () { intVStack s(SIZE); assert(s.OK()); for (int i = 0; i < SIZE; ++i) s.push(i); assert(s.length() == SIZE); assert(s.top() == (SIZE-1)); assert(s.full()); intVStack s1(SIZE); for (i = 0; i < SIZE; ++i) { int x = s.pop(); assert(x == (SIZE-1) - i); s1.push(x); } assert(s.empty()); assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s.OK()); assert(s1.OK()); intVStack s2 (s1); assert(s2.length() == SIZE); assert(s2.top() == 0); assert(s2.OK()); s1.clear(); assert(s1.empty()); s1 = s2; assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s1.OK()); s1.del_top(); assert(s1.length() == (SIZE-1)); assert(s1.top() == 1); cout << "s1:"; print(s1); assert(s.OK()); assert(s1.OK()); assert(s2.OK()); } #include "iSLStack.h" void SLtest () { intSLStack s; assert(s.OK()); for (int i = 0; i < SIZE; ++i) s.push(i); assert(s.length() == SIZE); assert(s.top() == (SIZE-1)); assert(!s.full()); intSLStack s1; for (i = 0; i < SIZE; ++i) { int x = s.pop(); assert(x == (SIZE-1) - i); s1.push(x); } assert(s.empty()); assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s.OK()); assert(s1.OK()); intSLStack s2 (s1); assert(s2.length() == SIZE); assert(s2.top() == 0); assert(s2.OK()); s1.clear(); assert(s1.empty()); s1 = s2; assert(s1.length() == SIZE); assert(s1.top() == 0); assert(s1.OK()); s1.del_top(); assert(s1.length() == (SIZE-1)); assert(s1.top() == 1); cout << "s1:"; print(s1); assert(s.OK()); assert(s1.OK()); assert(s2.OK()); } main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; start_timer(); cout << "XP stacks:\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "V stacks:\n"; Vtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "SL stacks:\n"; SLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; cout << "\nEnd of test\n"; } , char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; start_timer(); cout << "XP stacks:\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "V stacks:\n"; Vtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "SL stacks:\n"; SLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; cout << "\nEnd of test\n";libg++/tests/tLList.cc 644 473 0 12220 4677700032 10034 /* test/demo of linked structures */ #include #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } #include #include "iSLList.h" void printlist(intSLList& l) { for (Pix p = l.first(); p != 0; l.next(p)) cout << l(p) << " "; cout << "\n"; } void SLtest() { int i; intSLList a; assert(a.OK()); assert(a.empty()); cout << "prepending...\n"; for (i = 0; i < 10; ++i) { assert(a.length() == i); a.prepend(i); assert(a.front() == i); } cout << "a: "; printlist(a); cout << "appending...\n"; for (i = 0; i < 10; ++i) { assert(a.length() == 10 + i); a.append(i); assert(a.rear() == i); } cout << "a: "; printlist(a); intSLList b = a; cout << "b = a: " << "\n"; printlist(b); assert(b.OK()); assert(b.length() == a.length()); assert(b.front() == a.front()); assert(b.rear() == a.rear()); cout << "remove_front of first 10 elements:\n"; for (i = 0; i < 10; ++i) { assert(b.length() == 20 - i); assert(b.front() == 9 - i); b.remove_front(); } assert(b.length() == 10); cout << "b: "; printlist(b); cout << "inserting 100 after sixth element...\n"; Pix bp = b.first(); for (i = 0; i < 5; ++i) b.next(bp); b.ins_after(bp, 100); assert(b.length() == 11); cout << "b: "; printlist(b); a.join(b); cout << "after a.join(b)\n"; printlist(a); assert(b.empty()); assert(a.length() == 31); cout << "b: " << "\n"; printlist(b); b.prepend(999); cout << "b: " << "\n"; printlist(b); assert(b.length() == 1); assert(b.front() == 999); assert(b.rear() == 999); assert(b.OK()); intSLList bb = b; cout << "bb: " << "\n"; printlist(bb); assert(bb.OK()); assert(bb.length() == 1); assert(bb.front() == 999); assert(bb.rear() == 999); assert(bb.remove_front() == 999); b.prepend(1234); assert(b.length() == 2); b.del_after(b.first()); assert(b.rear() == 1234); assert(b.length() == 1); b.del_after(0); assert(b.length() == 0); assert(a.OK()); assert(b.OK()); assert(bb.OK()); } #include "iDLList.h" void printDlist(intDLList& l) { for (Pix p = l.first(); p != 0; l.next(p)) cout << l(p) << " "; cout << "\n"; } void DLtest() { int i; intDLList a; assert(a.OK()); assert(a.empty()); assert(a.length() == 0); cout << "prepending...\n"; for (i = 0; i < 10; ++i) { assert(a.length() == i); a.prepend(i); assert(a.front() == i); } cout << "a: " << "\n"; printDlist(a); cout << "appending...\n"; for (i = 0; i < 10; ++i) { assert(a.length() == 10 + i); a.append(i); assert(a.rear() == i); } cout << "a: "; printDlist(a); intDLList b = a; assert(b.OK()); assert(b.length() == a.length()); assert(b.front() == a.front()); assert(b.rear() == a.rear()); cout << "b = a: "; printDlist(b); cout << "remove_front of first 10 elements:\n"; for (i = 0; i < 10; ++i) { assert(b.length() == 20 - i); assert(b.front() == 9 - i); b.remove_front(); } assert(b.length() == 10); cout << "b: "; printDlist(b); cout << "inserting 100 after sixth element...\n"; Pix bp = b.first(); for (i = 0; i < 5; ++i) b.next(bp); b.ins_after(bp, 100); assert(b.length() == 11); cout << "b: "; printDlist(b); intDLList aa = a; aa.join(b); cout << "after aa = a; aa.join(b)\n"; printDlist(aa); assert(aa.length() == 31); assert(b.empty()); cout << "b: " << "\n"; printDlist(b); b.prepend(999); cout << "b: " << "\n"; printDlist(b); assert(b.length() == 1); assert(b.front() == 999); assert(b.rear() == 999); assert(b.OK()); intDLList bb = b; cout << "bb: " << "\n"; printDlist(bb); assert(bb.OK()); assert(bb.length() == 1); assert(bb.front() == 999); assert(bb.rear() == 999); assert(bb.remove_front() == 999); assert(bb.OK()); b.prepend(1234); assert(b.length() == 2); bp = b.first(); b.next(bp); b.del(bp, -1); assert(b.rear() == 1234); assert(b.length() == 1); b.del(bp); assert(b.length() == 0); intDLList z = a; cout << "z = a: "; printDlist(z); assert(z.OK()); assert(z.length() == 20); cout << "remove_rear of last 10 elements:\n"; for (i = 0; i < 10; ++i) { assert(z.length() == 20 - i); assert(z.rear() == 9 - i); z.remove_rear(); } assert(z.length() == 10); cout << "z: "; printDlist(z); cout << "inserting 100 before alternate elements...\n"; for (Pix zp = z.first(); zp; z.next(zp)) { z.ins_before(zp, 100); } assert(z.length() == 20); cout << "z: "; printDlist(z); cout << "inserting 200 after sixth element...\n"; zp = z.first(); for (i = 0; i < 5; ++i) z.next(zp); z.ins_after(zp, 200); assert(z.length() == 21); cout << "z: "; printDlist(z); cout << "deleting alternate elements of z..."; for (zp = z.first(); zp; z.next(zp)) { cout << z(zp) << " "; z.del(zp); } cout << "\n"; assert(z.length() == 10); cout << "z: "; printDlist(z); cout << "z in reverse order:\n"; for (zp = z.last(); zp; z.prev(zp)) cout << z(zp) << " "; cout << "\n"; z.clear(); assert(z.OK()); assert(z.empty()); assert(a.OK()); assert(b.OK()); } main() { SLtest(); DLtest(); cout << "\nEnd of test\n"; } out << "z: "; printDlist(z); cout << "deleting alternate elements of z..."; for (zp = z.first(); zp; z.next(zp)) { cout << z(zp) << " "; z.del(zp); } cout << "\n"; assert(z.length() == 10); cout << "z: "; printDlist(z); cout << "z in reverse order:\n"; for (zp = z.last(); zp; z.prev(zp)) cout << z(zp) << " "; cout << "\n"; z.clear()libg++/tests/twrapper.cc 644 473 0 13300 4677700032 10465 /* another test file for Integer class */ #include #include class MemoizedInteger; struct _Mrep { unsigned short Arity; // Arity of the function unsigned short ref; // reference count Integer (MemoizedInteger::*Fn)(...); // member function being memoized Integer Value; // value returned from function applied to arguments Integer *Args; // arguments to member function _Mrep (int arity = 0) { Arity = arity; ref = 1; Fn = 0; Args = new Integer [arity]; /* Value gets default initialization. */ } ~_Mrep () { if (--ref == 0) { delete [Arity] Args; delete Args; } } }; class MemoizedIntegerElem { _Mrep *rep; public: MemoizedIntegerElem (); MemoizedIntegerElem (MemoizedIntegerElem&); MemoizedIntegerElem (int, Integer (MemoizedInteger::*Fn)(...), Integer, ...); ~MemoizedIntegerElem (); void copy (const int, Integer (MemoizedInteger::*Fn)(...), Integer*); int operator==(MemoizedIntegerElem&); MemoizedIntegerElem& operator=(MemoizedIntegerElem&); MemoizedIntegerElem& operator=(const Integer& I) { rep->Value = I; return *this; } operator Integer () { return rep->Value; } friend ostream& operator<<(ostream&, MemoizedIntegerElem&); }; ostream& operator<<(ostream &strm, MemoizedIntegerElem &E) { strm << '['; for (int i = 0; i < E.rep->Arity; i++) strm << E.rep->Args[i] << ' '; strm << "=> " << E.rep->Value << ']'; return strm; } _Mrep _nil_Mrep; MemoizedIntegerElem::MemoizedIntegerElem () { rep = &_nil_Mrep; } MemoizedIntegerElem::MemoizedIntegerElem (MemoizedIntegerElem& E) { rep = E.rep; rep->ref++; } MemoizedIntegerElem::MemoizedIntegerElem (int arity, Integer (MemoizedInteger::*Fn)(...), Integer I, ...) { rep = &_nil_Mrep; copy (arity, Fn, &I); } void MemoizedIntegerElem::copy (const int arity, Integer (MemoizedInteger::*Fn)(...), Integer* pI) { if (rep == &_nil_Mrep) rep = new _Mrep (arity); else if (rep->ref > 1) { rep->ref--; rep = new _Mrep (arity); } else if (rep->Arity != arity) { delete rep; rep = new _Mrep (arity); } for (int i = 0; i < arity; i++) rep->Args[i] = pI[i]; rep->Fn = Fn; } MemoizedIntegerElem::~MemoizedIntegerElem () { if (rep != &_nil_Mrep && --rep->ref == 0) delete rep; } int MemoizedIntegerElem::operator==(MemoizedIntegerElem& E) { if (rep->Arity != E.rep->Arity || rep->Fn != E.rep->Fn) return 0; for (int i = 0; i < rep->Arity; i++) if (rep->Args[i] != E.rep->Args[i]) return 0; return 1; } MemoizedIntegerElem& MemoizedIntegerElem::operator=(MemoizedIntegerElem& E) { E.rep->ref++; if (rep != &_nil_Mrep && --rep->ref == 0) delete rep; rep = E.rep; return *this; } class MemoizedIntegerBase { int sz, start, finish; MemoizedIntegerElem *table; public: MemoizedIntegerBase (int size) { if (size < 0) { cerr << "table size < 0 not allowed, aborting...\n"; exit (-1); } sz = size; start = 0; finish = 0; table = new MemoizedIntegerElem [sz]; }; ~MemoizedIntegerBase () { if (start) delete [sz] table; else delete [finish] table; delete table; }; int indexOf (MemoizedIntegerElem&); MemoizedIntegerElem& at (int i) { return table[i]; } MemoizedIntegerElem* add (MemoizedIntegerElem&); }; MemoizedIntegerElem* MemoizedIntegerBase::add (MemoizedIntegerElem& E) { if (finish == sz) { start = 1; finish = 0; } else if (start) { start++; if (start == sz) start = 0; } if (finish < sz) table[finish++] = E; return &E; } int MemoizedIntegerBase::indexOf (MemoizedIntegerElem& E) { if (start) { for (int i = 0; i < sz; i++) { if (table[i] == E) return i; } } else { for (int i = 0; i < finish; i++) { if (table[i] == E) return i; } } return -1; } class MemoizedInteger : public MemoizedIntegerBase { public: MemoizedInteger(int size) :MemoizedIntegerBase(size) {} // wrappers Integer MemoizedInteger::() MemoizedInteger (int, Integer (MemoizedInteger::*)(Integer), Integer); Integer MemoizedInteger::() MemoizedInteger (int, Integer (MemoizedInteger::*)(Integer, Integer), Integer, Integer); // functions to be wrapped Integer factorial (Integer n); Integer fibonacci (Integer n); }; Integer MemoizedInteger::()MemoizedInteger (int, Integer (MemoizedInteger::*pf_I)(Integer), Integer I) { MemoizedIntegerElem E (1, pf_I, I); int i = this->indexOf (E); if (i < 0) { E = (this->*pf_I)(I); this->add (E); } else E = at (i); return E; } Integer MemoizedInteger::()MemoizedInteger (int, Integer (MemoizedInteger::*pf_I_I)(Integer, Integer), Integer I1, Integer I2) { MemoizedIntegerElem E (2, pf_I_I, I1, I2); int i = this->indexOf (E); if (i < 0) { E = (this->*pf_I_I)(I1, I2); this->add (E); } else E = at (i); return E; } Integer MemoizedInteger::factorial(Integer n) { Integer f = 1; while (n > 0) { f *= n; --n; } return f; } Integer MemoizedInteger::fibonacci(Integer n) { if (n <= 0) return 0; else { Integer f = 1; Integer prev = 0; while (n > 1) { Integer tmp = f; f += prev; prev = tmp; --n; } return f; } } main (int argc, char *argv[]) { _nil_Mrep.ref = (unsigned)(-1); int n; int size = (argc == 2 ? atoi (argv[1]) : 10); MemoizedInteger m (size); printf ("memoizing with table size %d\n", size); while (1) { cout << "Number: "; cin >> n; if (cin.eof() || n <= 0) { cout << "bye!\n"; break; } cout << n << "! = " << m.factorial (n) << "\n"; } } while (n > 1) { Integer tmp = f; f += prev; prev = tmp; --n; } return f; } } main (int argc, char *argv[]) { _nil_Mrep.ref = (unsigned)(-1); int n; int size = (argc == 2 ? atoi (argv[1]) : 10); MemoizedInteger m (size); printf ("memoizing with table size %d\n", size)libg++/tests/tFix.cc 644 473 0 4707 4677700033 7527 // // testFix.cc : test Fix (variable length) classes // #include overload check; overload checkb; void check(const char* x, Fix y) { cout << x << " = " << (y) << "\n"; } void check(const char* x, int y) { cout << x << " = " << (y) << "\n"; } void check(const char* x, double y) { cout << x << " = " << (y) << "\n"; } void checkb(const char* x, Fix y) { cout << x << " = " << (y) << " [" << length(y) << "]"<< "\n"; } main() { cout << "Fix: identities should be displayed\n" << "[X] displays the precision of a given value\n" << "[*] indicates that the full precision is not used for coding reasons\n"; Fix a; checkb("0 [16]",a); Fix b = .5; checkb(".5 [16]",b); Fix c(17,-.5); checkb("-.5 [17]",c); Fix d(33,.1); checkb(".1 [33]",d); Fix e = c; checkb("-.5 [17]",e); checkb(".3 [16]",a = .3); checkb(".5 [16]",a = b); checkb(".1 [16]",a = d); checkb(".1 [33*]",d = a); checkb("-.2 [17]",c = -.2); checkb("-.5 [17]",e); check(".1 [16] == .1 [33*]",a == d); d = .1; check(".1 [16] == .1 [33]",a == d); check(".1 [33] != .5 [16]",d != b); check(".1 [33] > .5 [16]",d > b); check(".1 [33] <= -.2 [17]",d <= c); e = .5; check("1073741824",mantissa(e)); check(".5",value(e)); checkb(".5 [17]",+e); checkb("-.5 [17]",-e); checkb(".1 [33] + .5 [16]",d+b); checkb(".1 [33] - .5 [16]",d-b); checkb(".1 [33] * .5 [16]",d*b); checkb(".1 [33] * 3",d*3); checkb(".1 [33] * -3",d*-3); checkb("-.1 [33] * 3",(-d)*3); checkb("-.1 [33] * -3",(-d)*-3); checkb(".5 [17] * -2",e*-2); checkb(".1 [33] % 25",d%25); checkb(".1 [33] % -25",d%-25); checkb(".1 [33] / .5 [16]",d/b); checkb(".1 [33] << 1",d<<1); checkb("-.1 [33] >> 2",(-d)>>2); checkb("abs(-.2)",abs(c)); checkb("abs(.2)",abs(-c)); check("sgn(-.2)",sgn(c)); check("sgn(.2)",sgn(-c)); cout << "\nshow .1 [33]\n"; show(d); Fix g = .95; cout << "\nFix: range errors warned\n"; Fix f = 1.1; checkb("1.1 [16]",f); checkb(".5 [16] / .1 [33]",b/d); checkb(".5 [16] / 0. [16]",b/Fix(0.)); checkb(".5 [17] * 32768",e*32768); cout << "\nFix: overflows saturated\n"; set_overflow_handler(Fix_overflow_saturate); checkb(".95 [16] + .1 [33]",g+d); checkb("-.1 [33] - .95 [16]",-d-g); checkb(".5 [17] * 2",e*2); cout << "\nFix: overflows generate warnings\n"; set_overflow_handler(Fix_overflow_warning); checkb(".95 [16] + .1 [33]",g+d); checkb("-.1 [33] - .95 [16]",-d-g); checkb(".5 [17] * 2",e*2); } checkb(".5 [16] / .1 [33]",b/d); checkb(".5 [16] / libg++/tests/tBitSet.cc 644 473 0 10360 4677700033 10203 /* a test/demo of BitSets */ #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << "OK\n"; \ else cerr << "Fail\n"; } #include void test3S(BitSet a, BitSet b, BitSet c) { // neg assert(~(~a) == a); // commutative assert((a | b) == (b | a)); assert((a & b) == (b & a)); // associative assert((a | (b | c)) == ((a | b) | c)); assert((a & (b & c)) == ((a & b) & c)); // distrib assert((a & (b | c)) == ((a & b) | (a & c))); assert((a | (b & c)) == ((a | b) & (a | c))); // absorption assert((a & (a | b)) == a); assert((a | (a & b)) == a); // demorgan assert((a | b) == ~(~a & ~b)); assert((a & b) == ~(~a | ~b)); // def of - assert((a - b) == (a & ~b)); assert(((a - b) | b) == (a | b)); // def of disjoint union assert((a ^ b) == ((a | b) & ~(a & b))); assert((a ^ b) == ((a - b) | (b - a))); BitSet x = a; x &= b; assert(x == (a & b)); x |= c; assert(x == ((a & b) | c)); x -= a; assert(x == (((a & b) | c) - a)); x ^= b; assert(x == ((((a & b) | c) - a) ^ b)); assert(x.OK()); } main() { cout << "BitSet tests:\n"; BitSet a; cout << "a = " << a << "\n"; assert(a.OK()); BitSet b = longtoBitSet(1024); cout << "b = " << b << "\n"; assert(b.OK()); assert(b[10] == 1); assert(b.count() == 1); b[0] = b[10]; assert(b[0] == 1); assert(b.count() == 2); BitSet c = atoBitSet("1010101010101010101010101010101010101010"); cout << "c = " << c << "\n"; assert(c.OK()); assert(c.count() == 20); for (int i = 0; i < 40; i += 2) { assert(c[i] == 1); assert(c[i+1] == 0); } for (int p = 0; p < 5; ++p) cout << "c[" << p << "] =" << int(c[p]) << "\n"; BitSet d = atoBitSet("0011001100110011001100110011001100110011"); cout << "d = " << d << "\n"; assert(d.OK()); assert(d.count() == 20); assert(d.count(0) == -1); BitSet e = atoBitSet("1111000011110000111100001111000011110000"); cout << "e = " << e << "\n"; assert(e.OK()); assert(e.count() == 20); BitSet u = ~a; cout << "u = ~a = " << u << "\n"; assert(a == ~u); BitSet g = ~e; cout << "g = ~e = " << g << "\n"; cout << "~c = " << (~c) << "\n"; cout << "c & d = " << (c & d) << "\n"; cout << "c | d = " << (c | d) << "\n"; cout << "c - d = " << (c - d) << "\n"; cout << "c ^ d = " << (c ^ d) << "\n"; test3S(b, c, d); test3S(a, a, a); test3S(a, b, c); test3S(a, c, b); test3S(c, b, a); test3S(c, c, c); test3S(c, d, e); test3S(e, d, c); BitSet f = b; cout << "f = b = " << f << "\n"; f &= c; cout << "f &= c = " << f << "\n"; f |= d; cout << "f |= d = " << f << "\n"; f -= e; cout << "f -= e = " << f << "\n"; f ^= u; cout << "f ^= u = " << f << "\n"; assert(f.OK()); assert(c != d); assert(!(c == d)); assert(!(c < d)); assert(!(c > d)); assert(!(c <= d)); assert(!(c >= d)); BitSet h = d; cout << "h = d\n:" << h << "\n"; assert(d == h); assert(d <= h); assert(d >= h); assert(!(d != h)); assert(!(d > h)); assert(!(d < h)); h.set(0); cout << "h.set(0):\n" << h << "\n"; assert(!(d == h)); assert(!(d >= h)); assert(!(d > h)); assert((d != h)); assert(d <= h); assert((d < h)); h.set(65); cout << "h.set(65):\n" << h << "\n"; assert(h[65] == 1); assert(h[64] == 0); assert(h[66] == 0); h.clear(2); cout << "h.clear(2):\n" << h << "\n"; assert(h[2] == 0); assert(h[3] == 1); assert(h[11] == 1); h.invert(11,20); cout << "h.invert(11,20):\n" << h << "\n"; assert(h[11] == 0); h.set(21,30); cout << "h.set(21,30):\n" << h << "\n"; assert(h[21] == 1); h.clear(31,40); cout << "h.clear(31, 40):\n" << h << "\n"; assert(h[33] == 0); cout << "h.test(0,5) = " << h.test(0, 5) << "\n"; cout << "h.test(31,40) = " << h.test(31, 40) << "\n"; cout << "set bits in e:\n"; for (p = e.first(); p >= 0; p = e.next(p)) { assert(e[p] == 1); cout << p << " "; } cout << "\n"; cout << "clear bits in g (reverse order):\n"; for (p = g.last(0); p >= 0; p = g.previous(p, 0)) { assert(g[p] == 0); cout << p << " "; } cout << "\n"; assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); assert(e.OK()); assert(f.OK()); assert(g.OK()); assert(h.OK()); cout << "\nEnd of test.\n"; } (31, 40) << "\n"; cout << "set bits in e:\n"; for (p = e.first(); p >= 0; p = e.next(p)) { assert(e[p] == 1); cout << p << " "; } cout << "\n"; cout << "clear bits in g (reverse order):\n"; for (p = g.last(0); p >= 0; p = g.previous(p, 0)) { libg++/tests/tRandom.cc 644 473 0 4660 4677700033 10217 /* a test file for Random classes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void demo(Random& r) { SampleStatistic s; cout << "five samples:\n"; for (int i = 0; i < 5; ++i) { double x = r(); cout << x << " "; s += x; } cout << "\nStatistics for 100 samples:\n"; for (; i < 100; ++i) { double x = r(); s += x; } cout << "samples: " << s.samples() << " "; cout << "min: " << s.min() << " "; cout << "max: " << s.max() << "\n"; cout << "mean: " << s.mean() << " "; cout << "stdDev: " << s.stdDev() << " "; cout << "var: " << s.var() << " "; cout << "confidence(95): " << s.confidence(95) << "\n"; } main() { int i; ACG gen1; cout << "five random ACG integers:\n"; for (i = 0; i < 5; ++i) cout << gen1.asLong() << " "; cout << "\n"; MLCG gen2; cout << "five random MLCG integers:\n"; for (i = 0; i < 5; ++i) cout << gen2.asLong() << " "; cout << "\n"; Binomial r1( 100, 0.5, &gen1); cout << "Binomial r1( 100, 0.50, &gen1) ...\n"; demo(r1); Erlang r2( 2.0, 0.5, &gen1); cout << "Erlang r2( 2.0, 0.5, &gen1) ...\n"; demo(r2); Geometric r3( 0.5, &gen1); cout << "Geometric r3(&gen1, 0.5)...\n"; demo(r3); HyperGeometric r4( 10.0, 150.0, &gen1); cout << "HyperGeometric r4( 10.0, 150.0, &gen1)...\n"; demo(r4); NegativeExpntl r5( 1.0, &gen1); cout << "NegativeExpntl r5( 1.0, &gen1)...\n"; demo(r5); Normal r6( 0.0, 1.0, &gen1); cout << "Normal r6( 0.0, 1.0, &gen1)...\n"; demo(r6); LogNormal r7( 1.0, 1.0, &gen1); cout << "LogNormal r7( 1.0, 1.0, &gen1)...\n"; demo(r7); Poisson r8( 2.0, &gen1); cout << "Poisson r8( 2.0, &gen1)...\n"; demo(r8); DiscreteUniform r9( 0, 1, &gen1); cout << "DiscreteUniform r9( 0.0, 1.0, &gen1)...\n"; demo(r9); Uniform r10( 0.0, 1.0, &gen1); cout << "Uniform r10( 0.0, 1.0, &gen1)...\n"; demo(r10); Weibull r11( 0.5, 1.0, &gen1); cout << "Weibull r11( 0.5, 1.0, &gen1)...\n"; demo(r11); cout << "SampleHistogram for 100 Normal samples\n"; SampleHistogram h(-4.0, 4.0); for (i = 0; i < 100; ++i) h += r6(); h.printBuckets(cout); cout << "\nEnd of test\n"; } r8( 2.0, &gen1)...\n"; demo(r8); DiscreteUniform r9( 0, 1, &gen1); cout #include #include "iQueue.h" #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } int SIZE; void print(intQueue& a) { int maxprint = 20; cout << "["; int k = 0; while (!a.empty() && k++ < maxprint) cout << a.deq() << " "; if (k == maxprint) cout << "]\n"; else { while (!a.empty()) a.del_front(); cout << "...]\n"; } assert(a.empty()); } #include "iXPQueue.h" void XPtest () { intXPQueue q(SIZE/2); assert(q.OK()); for (int i = 0; i < SIZE; ++i) q.enq(i); assert(q.length() == SIZE); assert(q.front() == 0); assert(!q.full()); intXPQueue q1(SIZE*2); for (i = 0; i < SIZE; ++i) { int x = q.deq(); assert(x == i); q1.enq(x); } assert(q.empty()); assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q.OK()); assert(q1.OK()); intXPQueue q2 (q1); assert(q2.length() == SIZE); assert(q2.front() == 0); assert(q2.OK()); q1.clear(); assert(q1.empty()); q1 = q2; assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q1.OK()); q1.del_front(); assert(q1.length() == (SIZE-1)); assert(q1.front() == 1); cout << "q1:"; print(q1); assert(q.OK()); assert(q1.OK()); assert(q2.OK()); } #include "iVQueue.h" void Vtest () { intVQueue q(SIZE); assert(q.OK()); for (int i = 0; i < SIZE; ++i) q.enq(i); assert(q.length() == SIZE); assert(q.front() == 0); assert(q.full()); intVQueue q1(SIZE); for (i = 0; i < SIZE; ++i) { int x = q.deq(); assert(x == i); q1.enq(x); } assert(q.empty()); assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q.OK()); assert(q1.OK()); intVQueue q2 (q1); assert(q2.length() == SIZE); assert(q2.front() == 0); assert(q2.OK()); q1.clear(); assert(q1.empty()); q1 = q2; assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q1.OK()); q1.del_front(); assert(q1.length() == (SIZE-1)); assert(q1.front() == 1); cout << "q1:"; print(q1); assert(q.OK()); assert(q1.OK()); assert(q2.OK()); } #include "iSLQueue.h" void SLtest () { intXPQueue q; assert(q.OK()); for (int i = 0; i < SIZE; ++i) q.enq(i); assert(q.length() == SIZE); assert(q.front() == 0); assert(!q.full()); intXPQueue q1; for (i = 0; i < SIZE; ++i) { int x = q.deq(); assert(x == i); q1.enq(x); } assert(q.empty()); assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q.OK()); assert(q1.OK()); intXPQueue q2 (q1); assert(q2.length() == SIZE); assert(q2.front() == 0); assert(q2.OK()); q1.clear(); assert(q1.empty()); q1 = q2; assert(q1.length() == SIZE); assert(q1.front() == 0); assert(q1.OK()); q1.del_front(); assert(q1.length() == (SIZE-1)); assert(q1.front() == 1); cout << "q1:"; print(q1); assert(q.OK()); assert(q1.OK()); assert(q2.OK()); } main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; start_timer(); cout << "XP queues:\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "V queues:\n"; Vtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "SL queues:\n"; SLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; cout << "\nEnd of test\n"; } , char** argc) { if libg++/tests/tPQ.cc 644 473 0 12503 4677700033 7332 /* a test file for PQs */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } #include "iPQ.h" int SIZE; int *nums; int *odds; int *dups; void add(int x[], intPQ& a) { for (int i = 0; i < SIZE; ++i) a.enq(x[i]); } #include MLCG randgen; void permute(int x[]) { for (int i = 1; i < SIZE; ++i) { int j = randgen.asLong() % (i + 1); int tmp = x[i]; x[i] = x[j]; x[j] = tmp; } } void makenums() { for (int i = 0; i < SIZE; ++i) nums[i] = i + 1; permute(nums); } void makeodds() { for (int i = 0; i < SIZE; ++i) odds[i] = 2 * i + 1; permute(odds); } void makedups() { for (int i = 0; i < SIZE; i += 2) dups[i] = dups[i+1] = i/2 + 1; permute(dups); } void printPQ(intPQ& a) { int maxprint = 20; cout << "["; int k = 0; for (Pix i = a.first(); i != 0 && k < maxprint; a.next(i),++k) cout << a(i) << " "; if (i != 0) cout << "...]\n"; else cout << "]\n"; } #include "iXPPQ.h" void XPtest() { intXPPQ a(SIZE); add(nums, a); intXPPQ b(SIZE); add(odds, b); intXPPQ c(SIZE); add(dups, c); intXPPQ d(a); add(nums, d); cout << "a: "; printPQ(a); cout << "b: "; printPQ(b); cout << "c: "; printPQ(c); cout << "d: "; printPQ(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE*2); assert(a.front() == 1); assert(b.front() == 1); assert(c.front() == 1); assert(d.front() == 1); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); d.del_front(); assert(d.front() == 1); for (j = 1; j <= SIZE; ++j) assert(a.deq() == j); assert(a.empty()); for (j = 1; j <= SIZE*2; j+=2) assert(b.deq() == j); assert(b.empty()); Pix indices[SIZE]; int m = 0; for (Pix i = c.first(); i != 0; c.next(i), c.next(i)) indices[m++] = i; assert(m == SIZE/2); while (--m >= 0) c.del(indices[m]); assert(c.length() == SIZE/2); int last = -1; j = 0; while (!c.empty()) { int current = c.deq(); assert(last <= current); last = current; ++j; } assert(j == SIZE/2); d.clear(); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iPHPQ.h" void PHtest() { intPHPQ a(SIZE); add(nums, a); intPHPQ b(SIZE); add(odds, b); intPHPQ c(SIZE); add(dups, c); intPHPQ d(a); add(nums, d); cout << "a: "; printPQ(a); cout << "b: "; printPQ(b); cout << "c: "; printPQ(c); cout << "d: "; printPQ(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE*2); assert(a.front() == 1); assert(b.front() == 1); assert(c.front() == 1); assert(d.front() == 1); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); d.del_front(); assert(d.front() == 1); for (j = 1; j <= SIZE; ++j) assert(a.deq() == j); assert(a.empty()); for (j = 1; j <= SIZE*2; j+=2) assert(b.deq() == j); assert(b.empty()); Pix indices[SIZE]; int m = 0; for (Pix i = c.first(); i != 0; c.next(i), c.next(i)) indices[m++] = i; assert(m == SIZE/2); while (--m >= 0) c.del(indices[m]); assert(c.length() == SIZE/2); int last = -1; j = 0; while (!c.empty()) { int current = c.deq(); assert(last <= current); last = current; ++j; } assert(j == SIZE/2); d.clear(); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iSplayPQ.h" void Splaytest() { intSplayPQ a; add(nums, a); intSplayPQ b; add(odds, b); intSplayPQ c; add(dups, c); intSplayPQ d(a); add(nums, d); cout << "a: "; printPQ(a); cout << "b: "; printPQ(b); cout << "c: "; printPQ(c); cout << "d: "; printPQ(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE*2); assert(a.front() == 1); assert(b.front() == 1); assert(c.front() == 1); assert(d.front() == 1); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); d.del_front(); assert(d.front() == 1); for (j = 1; j <= SIZE; ++j) assert(a.deq() == j); assert(a.empty()); for (j = 1; j <= SIZE*2; j+=2) assert(b.deq() == j); assert(b.empty()); Pix indices[SIZE]; int m = 0; for (Pix i = c.first(); i != 0; c.next(i), c.next(i)) indices[m++] = i; assert(m == SIZE/2); while (--m >= 0) c.del(indices[m]); assert(c.length() == SIZE/2); int last = -1; j = 0; while (!c.empty()) { int current = c.deq(); assert(last <= current); last = current; ++j; } assert(j == SIZE/2); d.clear(); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; nums = new int[SIZE]; odds = new int[SIZE]; dups = new int[SIZE]; makenums(); makeodds(); makedups(); start_timer(); cout << "Splaytest\n"; Splaytest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "PHtest\n"; PHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "XPtest\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; } 1; } else SIZE = 100; nums = new int[SIZE]; odds = new int[SIZE]; dups = new int[SIZE]; makenums(); makeodds(); makedups(); start_timer(); cout << "Splaytest\n"; Spllibg++/tests/tSet.cc 644 473 0 43435 4677700034 7556 /* a test file for sets */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } unsigned int hash(int x) { return multiplicativehash(x) ; } #include "iSet.h" int SIZE; int *nums; int *odds; int *dups; void printset(intSet& a) { int maxprint = 20; cout << "["; int k = 0; for (Pix i = a.first(); i != 0 && k < maxprint; a.next(i),++k) cout << a(i) << " "; if (i != 0) cout << "...]\n"; else cout << "]\n"; } void add(int x[], intSet& a) { for (int i = 0; i < SIZE; ++i) a.add(x[i]); } #include MLCG randgen; void permute(int x[]) { for (int i = 1; i < SIZE; ++i) { int j = randgen.asLong() % (i + 1); int tmp = x[i]; x[i] = x[j]; x[j] = tmp; } } void makenums() { for (int i = 0; i < SIZE; ++i) nums[i] = i + 1; } void makeodds() { for (int i = 0; i < SIZE; ++i) odds[i] = 2 * i + 1; permute(odds); } void makedups() { for (int i = 0; i < SIZE; i += 2) dups[i] = dups[i+1] = i/2 + 1; permute(dups); } void generictest(intSet& a, intSet& b, intSet& c) { c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); } #include "iXPSet.h" void XPtest() { intXPSet a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intXPSet b(SIZE); add(odds, b); assert(b.length() == SIZE); intXPSet c(SIZE); add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intXPSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iSLSet.h" void SLtest() { intSLSet a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intSLSet b; add(odds, b); assert(b.length() == SIZE); intSLSet c; add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intSLSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iVHSet.h" void VHtest() { intVHSet a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intVHSet b(SIZE); add(odds, b); assert(b.length() == SIZE); intVHSet c(SIZE); add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intVHSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iVOHSet.h" void VOHtest() { intVOHSet a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intVOHSet b(SIZE); add(odds, b); assert(b.length() == SIZE); intVOHSet c(SIZE); add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intVOHSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iCHSet.h" void CHtest() { intCHSet a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intCHSet b(SIZE); add(odds, b); assert(b.length() == SIZE); intCHSet c(SIZE); add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intCHSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iOXPSet.h" void OXPtest() { intOXPSet a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intOXPSet b(SIZE); add(odds, b); assert(b.length() == SIZE); intOXPSet c(SIZE); add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intOXPSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iOSLSet.h" void OSLtest() { intOSLSet a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intOSLSet b; add(odds, b); assert(b.length() == SIZE); intOSLSet c; add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intOSLSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iBSTSet.h" void BSTtest() { intBSTSet a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); a.balance(); assert(a.OK()); for ( j = 1; j <= SIZE; ++j) assert(a.contains(j)); intBSTSet b; add(odds, b); assert(b.length() == SIZE); intBSTSet c; add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intBSTSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iAVLSet.h" void AVLtest() { intAVLSet a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intAVLSet b; add(odds, b); assert(b.length() == SIZE); intAVLSet c; add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intAVLSet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iSplaySet.h" void Splaytest() { intSplaySet a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intSplaySet b; add(odds, b); assert(b.length() == SIZE); intSplaySet c; add(dups, c); assert(c.length() == SIZE/2); assert(c <= a); intSplaySet d(a); d &= b; cout << "a: "; printset(a); cout << "b: "; printset(b); cout << "c: "; printset(c); cout << "d: "; printset(d); assert(d.length() == SIZE/2); for (Pix p = d.first(); p; d.next(p)) assert((d(p) & 1) != 0); a.del(1); assert(a.length() == SIZE-1); assert(!a.contains(1)); c.clear(); assert(c.empty()); c |= a; assert(c == a); assert(c <= a); c.del(a(a.first())); assert(c <= a); assert(c != a); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c |= b; assert(b <= c); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c &= a; for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); c -= a; assert(!(a <= c)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; nums = new int[SIZE]; odds = new int[SIZE]; dups = new int[SIZE]; makenums(); makeodds(); makedups(); start_timer(); cout << "VHtest\n"; VHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "VOHtest\n"; VOHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "CHtest\n"; CHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "SLtest\n"; SLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "XPtest\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "OXPtest\n"; OXPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "OSLtest\n"; OSLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "BSTtest\n"; BSTtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "AVLtest\n"; AVLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "Splaytest\n"; Splaytest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; } ime(0.0) << "\n"; start_timer(); cout << "OSLtest\n"; OSLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "BSTtest\n"; BSTtest(); if (ptimes) cout << "\ntime = " < // a simple test/demo for CursesWindow int main() { CursesWindow big(23, 79, 0, 0); CursesWindow corner(10, 10, 0, 0); CursesWindow small(10, 10, 5, 5); CursesWindow sub(big, 10, 10, (big.height()>>1)-5, (big.width()>>1)-5); CursesWindow sub2(big, 5, 5, big.height()-6, big.width()-6); CursesWindow subsub(sub, 5, 5, 1, 1, 'r'); int i; char c='A'; big.box('B','B'); sub.box('|','-'); for (i=1;i<10;++i) sub.mvaddch(i, i, '*'); for (i=1;i<10;++i) sub.mvaddch(10-i, i, '*'); big.refresh(); big.mvprintw(0,0,"begx=%d,maxx=%d,begy=%d,maxy=%d,height=%d,width=%d", big.begx(), big.maxx(), big.begy(), big.maxy(), big.height(), big.width()); big.refresh(); sub2.box('2', '2'); subsub.box('s', 's'); big.refresh(); i=13; const char * cptr = "Cstar"; long l = 0xffffffff; double d= 3.1415926; float f= 10.0/d; big.mvprintw(2,2,"printw test:%d, %c, %s, %ld, %lf, %f\n",i,c,cptr,l,d,f); big.refresh(); corner.box('c','c'); big.mvprintw(5,20,"enter an int:"); big.refresh(); big.scanw("%d",&i); big.move(6,20); big.printw("number = %d\n",i); big.refresh(); corner.refresh(); small.box('S','S'); small.refresh(); big.mvprintw(20,20,"enter a char:"); big.refresh(); big.scanw("%c",&c); big.move(21,20); big.printw("char = %c\n",c); small.box(c, c); big.refresh(); small.refresh(); corner.overlay(small); big.overwrite(corner); corner.refresh(); } box('c','c'); big.mvprintw(5,20,"enter an int:"); big.refresh(); big.scanw("%d",&i); big.move(6,20); big.printw("number = %d\n",i); big.refresh(); corner.refresh(); small.box('S','S'); small.refresh(); big.mvprintw(20,20,"enter a char:"); big.refresh(); big.scanw("%c",&c); big.move(21,20); big.printw("char = %c\n",c); small.box(c, c); big.refresh(); small.refresh(); corner.overlibg++/tests/tList.cc 644 473 0 5401 4677700034 7705 /* test/demo of generic lists */ #include #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } #include #include "iList.h" int int_compare(int a, int b) { return a - b; } int inc(int x) { return x + 1; } int plus(int x, int y) { return x + y; } void printint(int x) { cout << x << " "; } void print(intList& l) { l.apply(printint); cout << "\n"; } int is_odd(int x) { return x & 1; } int is_even(int x) { return (x & 1) == 0; } intList sequence(int lo, int hi) { if (lo > hi) return intList(); else return intList(lo, sequence(lo+1, hi)); } #include MLCG randgen; intList randseq(int n) { if (n <= 0) return intList(); else return intList(randgen.asLong() % 50, randseq(--n)); } main() { intList a = sequence(1, 20); cout << "\nintList a = sequence(1, 20);\n"; print(a); assert(a.OK()); for (int i = 0; i < 20; ++i) assert(a[i] == i + 1); assert(a.position(2) == 1); intList b = randseq(20); cout << "\nintList b = randseq(20);\n"; print(b); intList c = concat(a, b); cout << "\nintList c = concat(a, b);\n"; print(c); assert(c.contains(a)); assert(c.contains(b)); assert(!(c.find(a).null())); assert(c.find(b) == b); intList d = map(inc, a); for (i = 0; i < 20; ++i) assert(d[i] == a[i] + 1); cout << "\nintList d = map(inc, a);\n"; print(d); intList e = reverse(a); cout << "\nintList e = reverse(a);\n"; print(e); for (i = 0; i < 20; ++i) assert(e[i] == a[19 - i]); intList f = select(is_odd, a); cout << "\nintList f = select(is_odd, a);\n"; print(f); intList ff = select(is_even, f); assert(ff.null()); int red = a.reduce(plus, 0); cout << "\nint red = a.reduce(plus, 0);\n"; cout << red; int second = a[2]; cout << "\nint second = a[2];\n"; cout << second; intList g = combine(plus, a, b); cout << "\nintList g = combine(plus, a, b);\n"; print(g); for (i = 0; i < 20; ++i) assert(g[i] == a[i] + b[i]); g.del((intPredicate)is_odd); cout << "\ng.del(is_odd);\n"; print(g); ff = select(is_odd, g); assert(ff.null()); b.sort(int_compare); for (i = 1; i < 20; ++i) assert(b[i] >= b[i-1]); cout << "\nb.sort(int_compare);\n"; print(b); intList h = merge(a, b, int_compare); cout << "\nintList h = merge(a, b, int_compare);\n"; print(h); for (i = 1; i < 40; ++i) assert(h[i] >= h[i-1]); for (Pix p = a.first(); p; a.next(p)) assert(h.contains(a(p))); for (p = b.first(); p; b.next(p)) assert(h.contains(b(p))); cout << "\nh via Pix:\n"; for (p = h.first(); p; h.next(p)) cout << h(p) << ", "; cout << "\n"; assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); assert(e.OK()); assert(f.OK()); assert(g.OK()); assert(h.OK()); cout << "\ndone\n"; } cout << "\nintList h = merge(a, b, int_compare);\n"; print(h); for (i = 1; i < 40; ++i) assert(h[i] >= h[i-1]); for (Pix p = a.first(); p; a.next(p)) assert(h.contains(a(p))); for (p = b.first(); p; b.next(p)) assert(h.contains(b(p))); cout << "\nlibg++/tests/test.hello.cc 644 473 0 6342 4677700034 10674 // This file tests the installation of the GNU C++ compiler system. // In order for this file to be compiled successfully, the compiler // driver (g++) must have execute paths to the preprocessor (cpp+) // and the compiler (c++), as well as the loader (ld++) and the // special run-time library (crt0+.o). In addition, the library // gnulib+ is needed to provide functions such as "_builtin_new" // and "_builtin_delete". #include "test0.h" extern "C" { #include } #include #if defined(MIPSEL) || defined(USG) #if !defined(hpux) #define exec aouthdr #define a_text text_start #define a_data data_start #endif #endif #ifdef __pyr__ #define MUST_MPROTECT #include extern "C" { int mprotect (char *, int, int); } #endif class tfile { public: char tname[L_tmpnam]; static char *orig_name; char *this_name; struct exec header; tfile (char*); ~tfile (); void* load (); }; tfile::tfile (char *p) { int fd; strcpy (tname, "hack.XXXXXX"); mktemp (tname); this_name = new char[strlen (p) + 1]; strcpy (this_name, p); if ((fd = open (this_name, 2, 0)) < 0) { fprintf (stderr, "Unable to open file %s\n", p); exit (1); } if (read (fd, (void*) &header, sizeof (header)) <= 0) { fprintf (stderr, "Error in reading file %s\n", p); } close (fd); } tfile::~tfile () { unlink (tname); } void *tfile::load () { int size = header.a_text + header.a_data; #ifdef EXEC_PAGESIZE int pagsiz = EXEC_PAGESIZE; #elif !defined(PAGSIZ) int pagsiz = getpagesize(); #else int pagsiz = PAGSIZ; #endif if (size < (pagsiz)) size = (pagsiz); int init_fn = (int) new short[size]; init_fn += pagsiz-1; init_fn &= ~(pagsiz-1); fprintf (stderr, "\n ... timing incremental load...\n"); char command[512], *cmd = command; sprintf (cmd, "time %s -N -A %s -T %x %s %s -o %s -lg++ -lc", LDXX, orig_name, init_fn, CRT1X, this_name, tname); if (system (cmd)) { fprintf (stderr, "Error in linking file bye\n"); delete this; exit (1); } int fd = open (tname, 2, 0); if (lseek (fd, sizeof (header), L_SET) < 0) { perror ("Error in temp file seek\n"); delete this; exit (1); } read (fd, (char*) init_fn, size); close (fd); #ifdef MUST_MPROTECT { void * rounded_size = (void *) ((size + pagsiz-1)&~(pagsiz-1)); int status = mprotect ((char*)init_fn, round_size, PROT_READ|PROT_EXEC|PROT_WRITE); if (status !=0 ) { perror ("making dynamically loaded code executable"); exit(errno); } } #endif /* MUST_MPROTECT */ fprintf (stderr, "load symbol-table at address 0x%x\n", init_fn); return (void *)init_fn; } ifile in ("/dev/tty"); ofile out ("/dev/tty"); main (int, char *argv[]) { char buf[4096]; out << "Enter file to link: (test.bye or test.bye2 or test.shell)\n"; in >> buf; out << "Hello! linking `" << buf << "'...\n"; tfile::orig_name = argv[0]; tfile temp (buf); register void (*init_fn)() = temp.load (); fprintf (stderr, "\n if execution now aborts, your crt1+.o is bad\n"); (*init_fn) (); out << "Enter another file to link: "; in >> buf; out << "Hello! linking `" << buf << "'...\n"; tfile temp2 (buf); init_fn = temp2.load (); (*init_fn)(); } char buf[4096]; out << "Enter file to link: (test.bye or test.bye2 or test.shell)\n"; in >> buf; out << "Hello! linking `" << buf << "'...\n"; tfile::orig_name = argv[0]; tfile temp (buf); register void (*init_fn)() = temp.load (); fprintf (stderr, "\n if execution nlibg++/tests/tGetOpt.cc 644 473 0 2442 4677700034 10176 #include int main (int argc, char **argv) { int digit_optind = 0; GetOpt getopt (argc, argv, "abc:d:0123456789"); while (1) { int this_option_optind = getopt.optind; int ch; if ((ch = getopt ()) == EOF) break; char c = char(ch); 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", getopt.optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (getopt.optind < argc) { printf ("non-option ARGV-elements: "); while (getopt.optind < argc) printf ("%s ", argv[getopt.optind++]); printf ("\n"); } return 0; } case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", getopt.optarg); break; case '?': break; default:libg++/tests/tBag.cc 644 473 0 33757 4677700035 7523 /* a test file for Bags */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } #include "iBag.h" unsigned int hash(int x) { return multiplicativehash(x) ; } int SIZE; int *nums; int *odds; int *dups; void add(int x[], intBag& a) { for (int i = 0; i < SIZE; ++i) a.add(x[i]); } #include MLCG randgen; void permute(int x[]) { for (int i = 1; i < SIZE; ++i) { int j = randgen.asLong() % (i + 1); int tmp = x[i]; x[i] = x[j]; x[j] = tmp; } } void makenums() { for (int i = 0; i < SIZE; ++i) nums[i] = i + 1; } void makeodds() { for (int i = 0; i < SIZE; ++i) odds[i] = 2 * i + 1; permute(odds); } void makedups() { for (int i = 0; i < SIZE; i += 2) dups[i] = dups[i+1] = i/2 + 1; permute(dups); } void printBag(intBag& a) { int maxprint = 20; cout << "["; int k = 0; for (Pix i = a.first(); i != 0 && k < maxprint; a.next(i),++k) cout << a(i) << " "; if (i != 0) cout << "...]\n"; else cout << "]\n"; } void generictest(intBag& a, intBag& b, intBag& c) { c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); } #include "iXPBag.h" void XPtest() { intXPBag a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intXPBag b(SIZE); add(odds, b); assert(b.length() == SIZE); intXPBag c(SIZE); add(dups, c); assert(c.length() == SIZE); intXPBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iSLBag.h" void SLtest() { intSLBag a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intSLBag b; add(odds, b); assert(b.length() == SIZE); intSLBag c; add(dups, c); assert(c.length() == SIZE); intSLBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iVHBag.h" void VHtest() { intVHBag a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intVHBag b(SIZE); add(odds, b); assert(b.length() == SIZE); intVHBag c(SIZE); add(dups, c); assert(c.length() == SIZE); intVHBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iCHBag.h" void CHtest() { intCHBag a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intCHBag b(SIZE); add(odds, b); assert(b.length() == SIZE); intCHBag c(SIZE); add(dups, c); assert(c.length() == SIZE); intCHBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iOXPBag.h" void OXPtest() { intOXPBag a(SIZE); add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intOXPBag b(SIZE); add(odds, b); assert(b.length() == SIZE); intOXPBag c(SIZE); add(dups, c); assert(c.length() == SIZE); intOXPBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iOSLBag.h" void OSLtest() { intOSLBag a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intOSLBag b; add(odds, b); assert(b.length() == SIZE); intOSLBag c; add(dups, c); assert(c.length() == SIZE); intOSLBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } #include "iSplayBag.h" void Splaytest() { intSplayBag a; add(nums, a); assert(a.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); intSplayBag b; add(odds, b); assert(b.length() == SIZE); intSplayBag c; add(dups, c); assert(c.length() == SIZE); intSplayBag d(a); add(nums, d); assert(d.length() == SIZE*2); cout << "a: "; printBag(a); cout << "b: "; printBag(b); cout << "c: "; printBag(c); cout << "d: "; printBag(d); for (j = 1; j <= SIZE; ++j) assert(d.nof(j) == 2); d.del(1); assert(d.nof(1) == 1); d.del(1); assert(d.nof(1) == 0); d.remove(2); assert(!d.contains(2)); for (Pix l = c.first(); l; c.next(l)) d.remove(c(l)); assert(d.length() == SIZE); c.clear(); assert(c.empty()); for (Pix k = a.first(); k != 0; a.next(k)) c.add(a(k)); for (k = a.first(); k != 0; a.next(k)) assert(c.contains(a(k))); c.del(a(a.first())); Pix i = a.first(); assert(!c.contains(a(i))); for (a.next(i); i != 0; a.next(i)) assert(c.contains(a(i))); c.add(a(a.first())); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = b.first(); k != 0; b.next(k)) c.add(b(k)); for (i = b.first(); i != 0; b.next(i)) assert(c.contains(b(i))); for (i = a.first(); i != 0; a.next(i)) assert(c.contains(a(i))); for (k = a.first(); k != 0; a.next(k)) c.remove(a(k)); for (i = a.first(); i != 0; a.next(i)) assert(!c.contains(a(i))); for (i = b.first(); i != 0; b.next(i)) c.del(b(i)); assert(c.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); generictest(a, b, c); } double return_elapsed_time ( double ); double start_timer ( void ); main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; nums = new int[SIZE]; odds = new int[SIZE]; dups = new int[SIZE]; makenums(); makeodds(); makedups(); start_timer(); cout << "VHtest\n"; VHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "CHtest\n"; CHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "SLtest\n"; SLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "XPtest\n"; XPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "Splaytest\n"; Splaytest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "OSLtest\n"; OSLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "OXPtest\n"; OXPtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; } _time(0.0) << "\nlibg++/tests/tMap.cc 644 473 0 16035 4677700035 7535 /* a test file for Maps */ #ifdef PTIMES const int ptimes = 1; #else const int ptimes = 0; #endif #include #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } #include "iMap.h" unsigned int hash(int x) { return multiplicativehash(x) ; } int SIZE; int *nums; int *odds; int *perm; void add(int x[], int y[], intintMap& a) { for (int i = 0; i < SIZE; ++i) a[x[i]] = y[i]; } #include MLCG randgen; void permute(int x[]) { for (int i = 1; i < SIZE; ++i) { int j = randgen.asLong() % (i + 1); int tmp = x[i]; x[i] = x[j]; x[j] = tmp; } } void makenums() { for (int i = 0; i < SIZE; ++i) nums[i] = i + 1; } void makeodds() { for (int i = 0; i < SIZE; ++i) odds[i] = 2 * i + 1; permute(odds); } void makeperm() { for (int i = 0; i < SIZE; ++i) perm[i] = i + 1; permute(perm); } void printMap(intintMap& a) { int maxprint = 20; cout << "["; int k = 0; for (Pix i = a.first(); i != 0 && k < maxprint; a.next(i),++k) cout << "(" << a.key(i) << ", " << a.contents(i) << ") "; if (i != 0) cout << "...]\n"; else cout << "]\n"; } #include "iSplayMap.h" void Splaytest() { intintSplayMap a(-1); add(nums, perm, a); intintSplayMap b(-1); add(perm, nums, b); intintSplayMap c(-1); add(perm, odds, c); intintSplayMap d(a); add(nums, nums, d); cout << "a: "; printMap(a); cout << "b: "; printMap(b); cout << "c: "; printMap(c); cout << "d: "; printMap(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); assert(a[SIZE+1] = -1); for (j = 1; j <= SIZE; ++j) assert(b.contains(j)); for (j = 1; j <= SIZE; ++j) assert(b[a[j]] == j); for (j = 1; j <= SIZE; ++j) assert(a[b[j]] == j); for (j = 1; j <= SIZE; ++j) assert((c[j] & 1) != 0); for (j = 1; j <= SIZE; ++j) assert(d[j] == j); d.del(1); assert(!d.contains(1)); for (j = 1; j <= SIZE; ++j) d.del(j); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iVHMap.h" void VHtest() { intintVHMap a(-1, SIZE); add(nums, perm, a); intintVHMap b(-1, SIZE); add(perm, nums, b); intintVHMap c(-1, SIZE); add(perm, odds, c); intintVHMap d(a); add(nums, nums, d); cout << "a: "; printMap(a); cout << "b: "; printMap(b); cout << "c: "; printMap(c); cout << "d: "; printMap(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); assert(a[SIZE+1] = -1); for (j = 1; j <= SIZE; ++j) assert(b.contains(j)); for (j = 1; j <= SIZE; ++j) assert(b[a[j]] == j); for (j = 1; j <= SIZE; ++j) assert(a[b[j]] == j); for (j = 1; j <= SIZE; ++j) assert((c[j] & 1) != 0); for (j = 1; j <= SIZE; ++j) assert(d[j] == j); d.del(1); assert(!d.contains(1)); for (j = 1; j <= SIZE; ++j) d.del(j); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iCHMap.h" void CHtest() { intintCHMap a(-1, SIZE); add(nums, perm, a); intintCHMap b(-1, SIZE); add(perm, nums, b); intintCHMap c(-1, SIZE); add(perm, odds, c); intintCHMap d(a); add(nums, nums, d); cout << "a: "; printMap(a); cout << "b: "; printMap(b); cout << "c: "; printMap(c); cout << "d: "; printMap(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); assert(a[SIZE+1] = -1); for (j = 1; j <= SIZE; ++j) assert(b.contains(j)); for (j = 1; j <= SIZE; ++j) assert(b[a[j]] == j); for (j = 1; j <= SIZE; ++j) assert(a[b[j]] == j); for (j = 1; j <= SIZE; ++j) assert((c[j] & 1) != 0); for (j = 1; j <= SIZE; ++j) assert(d[j] == j); d.del(1); assert(!d.contains(1)); for (j = 1; j <= SIZE; ++j) d.del(j); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iAVLMap.h" void AVLtest() { intintAVLMap a(-1); add(nums, perm, a); intintAVLMap b(-1); add(perm, nums, b); intintAVLMap c(-1); add(perm, odds, c); intintAVLMap d(a); add(nums, nums, d); cout << "a: "; printMap(a); cout << "b: "; printMap(b); cout << "c: "; printMap(c); cout << "d: "; printMap(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); assert(a[SIZE+1] = -1); for (j = 1; j <= SIZE; ++j) assert(b.contains(j)); for (j = 1; j <= SIZE; ++j) assert(b[a[j]] == j); for (j = 1; j <= SIZE; ++j) assert(a[b[j]] == j); for (j = 1; j <= SIZE; ++j) assert((c[j] & 1) != 0); for (j = 1; j <= SIZE; ++j) assert(d[j] == j); d.del(1); assert(!d.contains(1)); for (j = 1; j <= SIZE; ++j) d.del(j); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } #include "iRAVLMap.h" void RAVLtest() { intintRAVLMap a(-1); add(nums, perm, a); intintRAVLMap b(-1); add(perm, nums, b); intintRAVLMap c(-1); add(perm, odds, c); intintRAVLMap d(a); add(nums, nums, d); cout << "a: "; printMap(a); cout << "b: "; printMap(b); cout << "c: "; printMap(c); cout << "d: "; printMap(d); assert(a.length() == SIZE); assert(b.length() == SIZE); assert(c.length() == SIZE); assert(d.length() == SIZE); for (int j = 1; j <= SIZE; ++j) assert(a.contains(j)); for (j = 1; j <= a.length(); ++j) assert(a.rankof(j) == j); for (j = 1; j <= a.length(); ++j) assert(a.key(a.ranktoPix(j)) == j); assert(a[SIZE+1] = -1); for (j = 1; j <= SIZE; ++j) assert(b.contains(j)); for (j = 1; j <= SIZE; ++j) assert(b[a[j]] == j); for (j = 1; j <= SIZE; ++j) assert(a[b[j]] == j); for (j = 1; j <= SIZE; ++j) assert((c[j] & 1) != 0); for (j = 1; j <= SIZE; ++j) assert(d[j] == j); d.del(1); assert(!d.contains(1)); for (j = 1; j <= SIZE; ++j) d.del(j); assert(d.empty()); assert(a.OK()); assert(b.OK()); assert(c.OK()); assert(d.OK()); } double return_elapsed_time ( double ); double start_timer ( ); main(int argv, char** argc) { if (argv > 1) { SIZE = abs(atoi(argc[1])); SIZE &= ~1; } else SIZE = 100; nums = new int[SIZE]; odds = new int[SIZE]; perm = new int[SIZE]; makenums(); makeodds(); makeperm(); start_timer(); cout << "Splaytest\n"; Splaytest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "VHtest\n"; VHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "CHtest\n"; CHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "AVLtest\n"; AVLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "RAVLtest\n"; RAVLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; } psed_time(0.0) << "\n"; start_timer(); cout << "VHtest\n"; VHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "CHtest\n"; CHtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "AVLtest\n"; AVLtest(); if (ptimes) cout << "\ntime = " << return_elapsed_time(0.0) << "\n"; start_timer(); cout << "RAVLtest\n"; RAVLtest(); if (ptimes) cout << "\ntime = " << return_libg++/tests/tFix16.cc 644 473 0 4176 4677700035 7700 // // testFix16.cc : test Fix16/32 classes // #include #define check(x,y) cout << x << " = " << (y) << "\n" void test16() { cout << "Fix16: identities should be displayed\n"; Fix16 a; check("0",a); Fix16 b = .5; check(".5",b); Fix16 c = -.5; check("-.5",c); Fix16 d = .1; check(".1",d); Fix16 e = b; check(".5",e); check(".5",a = b); check(".25",a = .25); check("8192",mantissa(a)); mantissa(a)=8192; check(".25",a); check(".25",value(a)); check(".25",+a); check("-.25",-a); check(".1 + .5",d+b); check(".1 - .5",d-b); check(".1 * .5",d*b); check(".1 * 3",d*3); check(".1 * -3",d*-3); check(".1 / .5",d/b); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix16: range errors ignored and overflows saturated\n"; set_Fix16_overflow_handler(Fix16_overflow_saturate); set_Fix16_range_error_handler(Fix16_ignore); Fix16 f = 1.1; check("1.1",f); Fix16 g = .7; check(".7 + .5",g+b); check("-.5 - .7",c-g); check(".5 / .1",b/d); } void test32() { cout << "Fix32: identities should be displayed\n"; Fix32 a; check("0",a); Fix32 b = .5; check(".5",b); Fix32 c = -.5; check("-.5",c); Fix32 d = .1; check(".1",d); Fix32 e = b; check(".5",e); check(".5",a = b); check(".25",a = .25); check("536870912",mantissa(a)); mantissa(a)=536870912; check(".25",a); check(".25",value(a)); check(".25",+a); check("-.25",-a); check(".1 + .5",d+b); check(".1 - .5",d-b); check(".1 * .5",d*b); check(".1 * 3",d*3); check(".1 * -3",d*-3); check(".1 / .5",d/b); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix32: range errors reported and overflows reported\n"; set_Fix32_overflow_handler(Fix32_warning); set_Fix32_range_error_handler(Fix32_warning); Fix32 f = 1.1; check("1.1",f); Fix32 g = .7; check(".7 + .5",g+b); check("-.5 - .7",c-g); check(".5 / .1",b/d); } main() { test16(); test32(); } check(".1 / .5",d/b); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix32: range errors reported and overflows reported\n"; set_Fix32_overflow_handler(Fix32_warning); set_Fix32_range_error_handler(Fix32_warning); Fix32 f = 1.1; check("1.1",f); libg++/tests/tFix24.cc 644 473 0 4143 4677700035 7671 // // testFix24.cc : test Fix24/48 classes // #include #define check(x,y) cout << x << " = " << (y) << "\n" void test24() { cout << "Fix24: identities should be displayed\n"; Fix24 a; check("0",a); Fix24 b = .5; check(".5",b); Fix24 c = -.5; check("-.5",c); Fix24 d = .1; check(".1",d); Fix24 e = b; check(".5",e); check(".5",a = b); check(".25",a = .25); check("536870912",mantissa(a)); mantissa(a)=536870912; check(".25",a); check(".25",value(a)); check(".25",+a); check("-.25",-a); check(".1 + .5",d+b); check(".1 - .5",d-b); check(".1 * .5",d*b); check(".1 * 3",d*3); check(".1 * -3",d*-3); check(".1 / .5",d/b); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix24: range errors ignored and overflows saturated\n"; set_Fix24_overflow_handler(Fix24_overflow_saturate); set_Fix24_range_error_handler(Fix24_ignore); Fix24 f = 1.1; check("1.1",f); Fix24 g = .7; check(".7 + .5",g+b); check("-.5 - .7",c-g); check(".5 / .1",b/d); } void test48() { cout << "Fix48: identities should be displayed\n"; Fix48 a; check("0",a); Fix48 b = .5; check(".5",b); Fix48 c = -.5; check("-.5",c); Fix48 d = .1; check(".1",d); Fix48 e = b; check(".5",e); check(".5",a = b); check(".25",a = .25); twolongs t; t = mantissa(a); check("536870912",t.u); check("0",t.l); mantissa(a)=t; check(".25",a); check(".25",value(a)); check(".25",+a); check("-.25",-a); check(".1 + .5",d+b); check(".1 - .5",d-b); check(".1 * 3",d*3); check(".1 * -3",d*-3); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix48: range errors reported and overflows reported\n"; set_Fix48_overflow_handler(Fix48_warning); set_Fix48_range_error_handler(Fix48_warning); Fix48 f = 1.1; check("1.1",f); Fix48 g = .7; check(".7 + .5",g+b); check("-.5 - .7",c-g); } main() { test24(); test48(); } check(".1 * 3",d*3); check(".1 * -3",d*-3); check(".1 << 1",d<<1); check("-.5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix48: range errors reported and overflows reported\n"; set_Fix48_overflow_handler(Fix48_warning); set_Fix48_range_error_handler(Fix48_warning); Fix48 f = 1.1; check("1.1",f); Fixlibg++/tests/test.bye.cc 644 473 0 267 4677700035 10331 #include DECLARE_INIT_FUNCTION (init_1); #include "test0.h" static ofile bye ("/dev/tty"); static void init_1 () { bye << "And a very good bye from bye.cc!\n"; } .5 >> 2",c>>2); check(".1 == .5",d == b); check(".1 != .5",d != b); check(".1 > .5",d > b); check(".5 <= -.5",b <= c); cout << "Fix48: range errors reported and overflows reported\n"; set_Fix48_overflow_handler(Fix48_warning); set_Fix48_range_error_handler(Fix48_warning); Fix48 f = 1.1; check("1.1",f); Fixlibg++/tests/test0.h 644 473 0 2621 4677700035 7511 #include #include #include // change the following if ld++ and crt1+.o are in non-standard directories #ifndef LDXX #define LDXX "/usr/gnu/lib/gcc-ld" #endif #ifndef CRT1X #define CRT1X "/usr/gnu/lib/crt1+.o" #endif class ifile { FILE *fp; char *name; public: ifile (char *name) { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); if ((fp = fopen (name, "r")) == NULL) { fprintf (stderr, "could not open input file `%s'\n", name); exit (1); } } ~ifile () { fclose (fp); if (fp) fprintf (stderr, "closing input file `%s'\n", name); } ifile& operator>> (int &i) { fscanf (fp, "%d", &i); return *this; } ifile& operator>> (char *p) { fscanf (fp, "%s", p); return *this; } }; class ofile { FILE *fp; char *name; public: ofile (char *name) { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); if ((fp = fopen (name, "w")) == NULL) { fprintf (stderr, "could not open output file `%s'\n", name); exit (1); } } ~ofile () { fclose (fp); if (fp) fprintf (stderr, "closing output file `%s'\n", name); } ofile& operator<< (int i) { fprintf (fp, "%d", i); fflush (fp); return *this; } ofile& operator<< (char *p) { fprintf (fp, "%s", p); fflush (fp); return *this; } }; name) + 1]; strcpy (this->name, name); if ((fp = fopen (name, "w")) == NULL) { fprintf (stderr,libg++/tests/test.bye2.cc 644 473 0 270 4677700036 10406 #include DECLARE_INIT_FUNCTION (init_1); #include "test0.h" static ofile bye ("/dev/tty"); static void init_1 () { bye << "And a very good bye from bye2.cc!\n"; } ile& operator<< (int i) { fprintf (fp, "%d", i); fflush (fp); return *this; } ofile& operator<< (char *p) { fprintf (fp, "%s", p); fflush (fp); return *this; } }; name) + 1]; strcpy (this->name, name); if ((fp = fopen (name, "w")) == NULL) { fprintf (stderr,libg++/tests/test.shell.cc 644 473 0 324 4677700036 10654 #include DECLARE_INIT_FUNCTION (init_1); #include "test0.h" static ofile of ("/dev/tty"); static void init_1 () { of << "forking shell...\n"; system ("csh"); of << "shell exiting..."; } { fprintf (fp, "%d", i); fflush (fp); return *this; } ofile& operator<< (char *p) { fprintf (fp, "%s", p); fflush (fp); return *this; } }; name) + 1]; strcpy (this->name, name); if ((fp = fopen (name, "w")) == NULL) { fprintf (stderr,libg++/tests/tgwrapper.cc 644 473 0 24604 4677700036 10651 /* another test file for Integer class */ #include #include #define INLINE #define MEMOIZE_TYPE(TYPE) \ class Memoized ## TYPE; \ struct _Memoized ## TYPE ## _rep \ { \ unsigned short Arity; /* Arity of the function */ \ unsigned short Ref; /* Reference count */ \ TYPE (Memoized ## TYPE::*Fn)(...); /* member function being memoized */ \ TYPE Value; /* value returned from function applied to arguments */ \ TYPE *Args; /* arguments to member function */ \ \ INLINE _Memoized ## TYPE ## _rep (int arity = 0) \ { \ Arity = arity; \ Ref = 1; \ Fn = 0; \ Args = new TYPE [arity]; \ /* Value gets default initilaization. */ \ } \ INLINE ~_Memoized ## TYPE ## _rep () \ { \ if (--Ref == 0) \ { \ delete [Arity] Args; \ delete Args; \ } \ } \ }; \ \ /* Declare `NIL' for this type. */ \ _Memoized ## TYPE ## _rep _nil_ ## TYPE ## _rep; \ void init_nil() { _nil_ ## TYPE ## _rep.Ref = (unsigned)(-1); } \ \ class Memoized ## TYPE ## Elem \ { \ _Memoized ## TYPE ## _rep *rep; \ public: \ INLINE Memoized ## TYPE ## Elem () \ { rep = &_nil_ ## TYPE ## _rep; } \ INLINE Memoized ## TYPE ## Elem (Memoized ## TYPE ## Elem& E) \ { rep = E.rep; rep->Ref++; } \ Memoized ## TYPE ## Elem (int arity, TYPE (Memoized ## TYPE::*Fn)(...), TYPE x, ...) \ { rep = &_nil_ ## TYPE ## _rep; copy (arity, Fn, &x); } \ INLINE ~Memoized ## TYPE ## Elem () \ { if (rep != &_nil_ ## TYPE ## _rep && --rep->Ref == 0) delete rep; } \ \ void copy (const int, TYPE (Memoized ## TYPE::*Fn)(...), TYPE*); \ int operator==(Memoized ## TYPE ## Elem&); \ Memoized ## TYPE ## Elem& operator=(Memoized ## TYPE ## Elem&); \ INLINE Memoized ## TYPE ## Elem& operator=(const TYPE& x) { rep->Value = x; return *this; } \ INLINE operator TYPE () { return rep->Value; } \ }; \ \ void Memoized ## TYPE ## Elem::copy \ (const int arity, TYPE (Memoized ## TYPE::*Fn)(...), TYPE* pI) \ { \ if (rep == &_nil_ ## TYPE ## _rep) \ rep = new _Memoized ## TYPE ## _rep (arity); \ else if (rep->Ref > 1) \ { \ rep->Ref--; \ rep = new _Memoized ## TYPE ## _rep (arity); \ } \ else if (rep->Arity != arity) \ { \ delete rep; \ rep = new _Memoized ## TYPE ## _rep (arity); \ } \ for (int i = 0; i < arity; i++) \ rep->Args[i] = pI[i]; \ rep->Fn = Fn; \ } \ \ int Memoized ## TYPE ## Elem::operator==(Memoized ## TYPE ## Elem& E) \ { \ if (rep->Arity != E.rep->Arity || rep->Fn != E.rep->Fn) \ return 0; \ for (int i = 0; i < rep->Arity; i++) \ if (rep->Args[i] != E.rep->Args[i]) \ return 0; \ return 1; \ } \ \ Memoized ## TYPE ## Elem& Memoized ## TYPE ## Elem::operator=(Memoized ## TYPE ## Elem& E) \ { \ E.rep->Ref++; \ if (rep != &_nil_ ## TYPE ## _rep && --rep->Ref == 0) delete rep; \ rep = E.rep; \ return *this; \ } \ /* End of MEMOIZE_TYPE. */ #define DEFINE_MEMOIZATION(TYPE, CTOR_ARGS, CTOR_BODY, DTOR_BODY) \ MEMOIZE_TYPE (TYPE); \ class Memoized ## TYPE ## Base \ { \ int sz, start, finish; \ Memoized ## TYPE ## Elem *table; \ public: \ Memoized ## TYPE ## Base CTOR_ARGS CTOR_BODY \ ~Memoized ## TYPE ## Base () DTOR_BODY \ \ Memoized ## TYPE ## Elem* add (Memoized ## TYPE ## Elem&); \ Memoized ## TYPE ## Elem* remove (Memoized ## TYPE ## Elem&); \ int indexOf (Memoized ## TYPE ## Elem&); \ Memoized ## TYPE ## Elem& at (int); \ }; \ #define DEFINE_ADD(TYPE, DECL, BODY) \ Memoized ## TYPE ## Elem* Memoized ## TYPE ## Base::add (Memoized ## TYPE ## Elem& DECL) BODY #define DEFINE_REMOVE(TYPE, DECL, BODY) \ Memoized ## TYPE ## Elem* Memoized ## TYPE ## Base::remove (Memoized ## TYPE ## Elem& DECL) BODY #define DEFINE_INDEXOF(TYPE, INDEX_TYPE, DECL, BODY) \ INDEX_TYPE Memoized ## TYPE ## Base::indexOf (Memoized ## TYPE ## Elem& DECL) BODY #define DEFINE_AT(TYPE, INDEX_TYPE, DECL, BODY) \ Memoized ## TYPE ## Elem& Memoized ## TYPE ## Base::at (INDEX_TYPE DECL) BODY #define DEFINE_MEMOIZED_CLASS(TYPE, CLASS_BODY) \ class Memoized ## TYPE : public Memoized ## TYPE ## Base CLASS_BODY #define DEFINE_BASE_CTOR(TYPE) \ Memoized ## TYPE (int size) :Memoized ## TYPE ## Base(size) {} #define DEFINE_WRAPPER_1(TYPE) \ TYPE Memoized ## TYPE::()Memoized ## TYPE \ (int, TYPE (Memoized ## TYPE::*pf_I)(TYPE), TYPE I) \ { \ Memoized ## TYPE ## Elem E (1, pf_I, I); \ int i = this->indexOf (E); \ \ if (i < 0) \ { \ E = (this->*pf_I)(I); \ this->add (E); \ } \ else \ E = at (i); \ \ return E; \ } \ #define DEFINE_WRAPPER_2(TYPE) \ TYPE Memoized ## TYPE::()Memoized ## TYPE \ (int, TYPE (Memoized ## TYPE::*pf_I_I)(TYPE, TYPE), TYPE I1, TYPE I2) \ { \ Memoized ## TYPE ## Elem E (2, pf_I_I, I1, I2); \ int i = this->indexOf (E); \ \ if (i < 0) \ { \ E = (this->*pf_I_I)(I1, I2); \ this->add (E); \ } \ else \ E = at (i); \ \ return E; \ } \ #define DEFINE_WRAPPER_3(TYPE) \ TYPE Memoized ## TYPE::()Memoized ## TYPE \ (int, TYPE (Memoized ## TYPE::*pf_I_I_I)(TYPE, TYPE, TYPE), TYPE I1, TYPE I2, TYPE I3) \ { \ Memoized ## TYPE ## Elem E (3, pf_I_I, I1, I2, I3); \ int i = this->indexOf (E); \ \ if (i < 0) \ { \ E = (this->*pf_I_I_I)(I1, I2, I3); \ this->add (E); \ } \ else \ E = at (i); \ \ return E; \ } \ #define DEFINE_WRAPPER_4(TYPE) \ TYPE Memoized ## TYPE::()Memoized ## TYPE \ (int, TYPE (Memoized ## TYPE::*pf_I_I_I_I)(TYPE, TYPE, TYPE, TYPE), \ TYPE I1, TYPE I2, TYPE I3, TYPE I4) \ { \ Memoized ## TYPE ## Elem E (2, pf_I_I_I_I, I1, I2, I3, I4); \ int i = this->indexOf (E); \ \ if (i < 0) \ { \ E = (this->*pf_I_I_I_I)(I1, I2, I3, I4); \ this->add (E); \ } \ else \ E = at (i); \ \ return E; \ } \ #define DEFINE_MEMOIZED_FUNCTION(TYPE, NAME, ARGS, BODY) \ TYPE Memoized ## TYPE:: NAME ARGS BODY #define MEMOIZED_TABLE(TYPE, DECL, ARGS) \ Memoized ## TYPE DECL ARGS /* Define a memoization for class `Integer'. The initialization argument list for the constructor is `(int size)'. The bodies of the constructor taking that argument list, and the destructor are also given in this macro. */ DEFINE_MEMOIZATION (Integer, (int size), { if (size < 0) { cerr << "table size < 0 not allowed, aborting...\n"; exit (-1); } sz = size; start = 0; finish = 0; table = new MemoizedIntegerElem [sz]; }, { if (start) delete [sz] table; else delete [finish] table; /* delete table; */ }); /* Give the implementation of the memoization. In this implementation, the memization table is just a circular buffer of some fixed size. */ DEFINE_ADD (Integer, E, { if (finish == sz) { start = 1; finish = 0; } else if (start) { start++; if (start == sz) start = 0; } if (finish < sz) table[finish++] = E; return &E; }); DEFINE_REMOVE (Integer, E, { return &E/* does nothing, except uses it. */;}); DEFINE_INDEXOF (Integer, int, E, { int i; if (start) { for (i = 0; i < sz; i++) { if (table[i] == E) return i; } } else { for (i = 0; i < finish; i++) { if (table[i] == E) return i; } } return -1; }); DEFINE_AT (Integer, int, i, { return table[i]; }); DEFINE_MEMOIZED_CLASS (Integer, { public: DEFINE_BASE_CTOR(Integer); // wrappers DEFINE_WRAPPER_1 (Integer); // functions to be wrapped Integer factorial (Integer n); Integer fibonacci (Integer n); }); DEFINE_MEMOIZED_FUNCTION (Integer, factorial, (Integer n), { Integer f = 1; while (n > 0) { f *= n; --n; } return f; }); DEFINE_MEMOIZED_FUNCTION (Integer, fibonacci, (Integer n), { if (n <= 0) return 0; else { Integer f = 1; Integer prev = 0; while (n > 1) { Integer tmp = f; f += prev; prev = tmp; --n; } return f; } }); main (int argc, char *argv[]) { int n; int size = (argc == 2 ? atoi (argv[1]) : 10); init_nil(); MEMOIZED_TABLE (Integer, m, (size)); printf ("memoizing with table size %d\n", size); while (1) { cout << "Number: "; cin >> n; if (cin.eof() || n <= 0) { cout << "bye!\n"; break; } cout << n << "! = " << m.factorial (n) << "\n"; } } prev = 0; while (n > 1) { Integer tmp = f; f += prev; prev = tmp; --n; } return f; } });libg++/tests/tPQ.inp 644 473 0 0 4677700036 7423 libg++/tests/tFile.cc 644 473 0 14455 4677700037 7705 // This may look like C code, but it is really -*- C++ -*- /* * a few tests for streams * */ #include #include #include #include #include class record { public: char c; int i; double d; }; ostream& operator<<(ostream& s, record& r) { return(s << "(i = " << r.i << " c = " << r.c << " d = " << r.d << ")"); } void t1() { char ch; assert(cout.good()); assert(cout.writable()); assert(cout.is_open()); cout << "Hello, world via cout\n"; assert(cerr.good()); assert(cerr.writable()); assert(cerr.is_open()); cerr << "Hello, world via cerr\n"; assert(cin.good()); assert(cin.readable()); assert(cin.is_open()); cout << "enter a char:"; cin >> ch; cout.put('c'); cout.put(' '); cout.put('='); cout.put(' '); cout.put('"'); cout.put(ch); cout << '"'; cout << char('\n'); assert(cin.good()); assert(cout.good()); } void t2() { int i; short h; long l; float f; double d; char s[100]; cout << "enter three integers (short, int, long):"; cin >> h; cin >> i; // cin.scan("%ld", &l); cin >> l; cout << "first = " << h << " via dec = " << dec(h, 8) << "\n"; cout << "second = " << i << form(" via form = %d = 0%o", i, i); cout.form(" via cout.form = %d = 0x%x\n", i, i); cout << "third = " << l << " via hex = " << hex(l) << "\n"; assert(cin.good()); assert(cout.good()); cout << "enter a float then a double:"; cin >> f; cin >> d; cout << "first = " << f << "\n"; cout << "second = " << d << "\n"; assert(cin.good()); assert(cout.good()); cout << "enter 5 characters separated with spaces:"; cin >> s; cout << "first = " << s << "\n"; cin.get(s, 100); cout << "rest = " << s << "\n"; assert(cin.good()); assert(cout.good()); } void t3() { char ch; cout << "\nMaking streams sout and sin..."; ostream sout("streamfile", io_writeonly, a_create); assert(sout.good()); assert(sout.is_open()); assert(sout.writable()); assert(!sout.readable()); sout << "This file has one line testing output streams.\n"; sout.close(); assert(!sout.is_open()); istream sin("streamfile", io_readonly, a_useonly); assert(sin.good()); assert(sin.is_open()); assert(!sin.writable()); assert(sin.readable()); cout << "contents of file:\n"; while(sin >> ch) cout << ch; sin.close(); assert(!sin.is_open()); } void t4() { char s[100]; char ch; int i; cout << "\nMaking File tf ... "; File tf("tempfile", io_readwrite, a_create); assert(tf.good()); assert(tf.is_open()); assert(tf.writable()); assert(tf.readable()); strcpy(s, "This is the first and only line of this file.\n"); tf.put(s); tf.seek(0); tf.get(s, 100); assert(tf.good()); cout << "first line of file:\n" << s << "\n"; cout << "next char = "; tf.get(ch); cout << (int)ch; cout.put('\n'); assert(ch == 10); strcpy(s, "Now there is a second line.\n"); cout << "reopening tempfile, appending: " << s; tf.open(tf.name(), io_appendonly, a_use); assert(tf.good()); assert(tf.is_open()); assert(tf.writable()); assert(!tf.readable()); tf.put(s); assert(tf.good()); tf.open(tf.name(), io_readonly, a_use); tf.raw(); assert(tf.good()); assert(tf.is_open()); assert(!tf.writable()); assert(tf.readable()); cout << "First 10 chars via raw system read after reopen for input:\n"; read(tf.filedesc(), s, 10); assert(tf.good()); for (i = 0; i < 10; ++ i) cout.put(s[i]); lseek(tf.filedesc(), 5, 0); cout << "\nContents after raw lseek to pos 5:\n"; while ( (tf.get(ch)) && (cout.put(ch)) ); tf.remove(); assert(!tf.is_open()); } void t5() { record r; int i; cout << "\nMaking SFile rf..."; SFile rf("recfile", sizeof(record), io_readwrite, a_create); assert(rf.good()); assert(rf.is_open()); assert(rf.writable()); assert(rf.readable()); for (i = 0; i < 10; ++i) { r.c = i + 'a'; r.i = i; r.d = (double)(i) / 1000.0; rf.put(&r); } assert(rf.good()); cout << "odd elements of file in reverse order:\n"; for (i = 9; i >= 0; i -= 2) { rf[i].get(&r); assert(r.c == i + 'a'); assert(r.i == i); cout << r << "\n"; } assert(rf.good()); rf.remove(); assert(!rf.is_open()); } void t6() { cout << "\nMaking PlotFile pf ..."; PlotFile pf("plot.out", io_writeonly, a_create); assert(pf.good()); assert(pf.is_open()); assert(pf.writable()); assert(!pf.readable()); pf.move(10,10); pf.label("Test"); pf.circle(300,300,200); pf.line(100, 100, 500, 500); assert(pf.good()); cout << "(You may delete or attempt to plot " << pf.name() << ")\n"; } void t7() { char ch; char mybuf[1000]; cout << "creating string-based ostream...\n"; ostream strout(1000, mybuf); assert(strout.good()); assert(strout.writable()); strout << "This is a string-based stream.\n"; strout << "With two lines.\n"; strout.put(char(0)); assert(strout.good()); cout << "with contents:\n"; cout << mybuf; cout << "using it to create string-based istream...\n"; istream strin(strlen(mybuf), mybuf); assert(strin.good()); assert(strin.readable()); cout << "with contents:\n"; while (strin.get(ch)) cout.put(ch); } void t8() { cout << "\nThe following file open should generate error message:"; cout.flush(); File ef("shouldnotexist", io_readonly, a_useonly); assert(!ef.good()); assert(!ef.is_open()); } void t9() { char ch; cout << "\nMaking filebuf streams fout and fin..."; filebuf foutbuf; foutbuf.open("ffile", output); ostream fout(&foutbuf); assert(fout.good()); assert(fout.is_open()); assert(fout.writable()); assert(!fout.readable()); fout << "This file has one line testing output streams.\n"; fout.close(); assert(!fout.is_open()); filebuf finbuf; finbuf.open("ffile", input); istream fin(&finbuf); assert(fin.good()); assert(fin.is_open()); assert(!fin.writable()); assert(fin.readable()); cout << "contents of file:\n"; while(fin >> ch) cout << ch; fin.close(); assert(!fin.is_open()); } main() { t1(); t2(); t3(); t4(); t5(); t6(); t7(); t9(); t8(); cout << "\nFinal names & states:\n"; cout << "cin: " << cin.name() << "\t" << cin.rdstate() << "\n"; cout << "cout: " << cout.name() << "\t" << cout.rdstate() << "\n"; cout << "cerr: " << cerr.name() << "\t" << cerr.rdstate() << "\n"; cout << "\nend of test.\n"; } e()); assert(fin.readable()); cout << "contents of file:\n"; while(fin >> ch) cout << ch; fin.close(); assert(!fin.is_open()); } main() { t1(); t2(); t3(); t4(); t5(); t6(); t7(); t9()libg++/tests/tRational.cc 644 473 0 10506 4677700037 10570 /* a test file for Rational class */ #include #include #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } void identtest(Rational& a, Rational& b, Rational& c) { Rational one(1, 1); assert(-(-a) == a); assert((a + b) == (b + a)); assert((a + (-b)) == (a - b)); assert((a * b) == (b * a)); assert((a * (-b)) == -(a * b)); assert((a / (-b)) == -(a / b)); assert((a / b) == (a * (one / b))); assert((a / b) == (one / (b / a))); assert((a - b) == -(b - a)); assert((a + (b + c)) == ((a + b) + c)); assert((a * (b * c)) == ((a * b) * c)); assert((a * (b + c)) == ((a * b) + (a * c))); assert(((a - b) + b) == a); assert(((a + b) - b) == a); assert(((a * b) / b) == a); assert(((a / b) * b) == a); Rational x = a; x *= b; assert(x == (a * b)); x += c; assert(x == ((a * b) + c)); x -= a; assert(x == (((a * b) + c) - a)); x /= b; assert(x == ((((a * b) + c) - a) / b)); assert(x.OK()); } void simpletest() { Rational one = 1; assert(one.OK()); Rational third(1, 3); assert(third.OK()); Rational half(1, 2); assert(half.OK()); cout << "one = " << one << "\n"; cout << "third = " << third << "\n"; cout << "half = " << half << "\n"; cout << "third + half = " << third + half << "\n"; cout << "third - half = " << third - half << "\n"; cout << "third * half = " << third * half << "\n"; cout << "third / half = " << third / half << "\n"; Rational onePointTwo = 1.2; cout << "onePointTwo = " << onePointTwo << "\n"; cout << "double(onePointTwo) = " << double(onePointTwo) << "\n"; Rational a = one; cout << "a = " << a << "\n"; assert(a.OK()); a += half; cout << "a += half = " << a << "\n"; assert(a == Rational(3, 2)); a -= half; cout << "a -= half = " << a << "\n"; assert(a == Rational(1)); a *= half; cout << "a *= half = " << a << "\n"; assert(a == half); a /= half; cout << "a /= half = " << a << "\n"; assert(a == Rational(1)); assert(a.OK()); identtest(one, one, one); identtest(one, third, half); identtest(third, half, one); identtest(onePointTwo, half, a); } void pitest() { Rational half(1, 2); Rational approxpi(355, 113); assert(approxpi.OK()); cout << "approxpi = " << approxpi << "\n"; cout << "double(approxpi) = " << double(approxpi) << "\n"; Rational rpi = Rational(PI); cout << "rpi = Rational(PI) = " << rpi << "\n"; assert(rpi.OK()); cout << "double(rpi) = " << double(rpi) << "\n"; cout << "approxpi + rpi = " << approxpi + rpi << "\n"; cout << "approxpi - rpi = " << approxpi - rpi << "\n"; cout << "approxpi * rpi = " << approxpi * rpi << "\n"; cout << "approxpi / rpi = " << approxpi / rpi << "\n"; Rational negapproxpi = -approxpi; cout << "-approxpi = " << negapproxpi << "\n"; assert(sign(negapproxpi) < 0); cout << "abs(negapproxpi) = " << abs(negapproxpi) << "\n"; assert(abs(negapproxpi) == approxpi); assert(approxpi != rpi); assert(approxpi >= rpi); assert(approxpi > rpi); assert(!(approxpi == rpi)); assert(!(approxpi <= rpi)); assert(!(approxpi < rpi)); assert((approxpi >? rpi) == approxpi); assert((approxpi > a; cout << "number = " << a << "\n"; assert(a.OK()); } // as a fct just to test Rational fcts Rational estimate_e(long n) { Rational x = Rational(n + 1, n); Rational e = pow(x, n); return e; } void etest(long n) { cout << "approximating e as pow(1+1/n),n) for n =" << n << "\n"; Rational approxe = estimate_e(n); assert(approxe.OK()); cout << "double(approxe) = " << double(approxe) << "\n"; cout << "log(approxe) = " << log(approxe) << "\n"; assert(log(approxe) <= 1.0); cout << "approxe = " << approxe << "\n"; } main() { simpletest(); pitest(); IOtest(); etest(10); etest(100); etest(1000); cout << "\nEnd of test\n"; } (n + 1, n); Rational e = pow(x, n); return e; } void etest(long n) { cout << "approximating e as pow(1+1/n),n) for n =" << n << "\n"; Rational approxe = estimate_e(n); assert(libg++/tests/tBitString.cc 644 473 0 16623 4677700037 10732 /* a test/demo of BitStrings */ #include #define tassert(ex) { cerr << #ex; \ if ((ex)) cerr << " OK\n"; \ else cerr << " Fail\n"; } #include void doubletest(BitString a) { BitString x; BitString y; x = a + reverse(a); for (int i = 0; i < 7; ++i) { y = x; x += x; assert(x == reverse(x)); assert(x.index(y) == 0); assert(x.index(y, -1) == x.length() / 2); assert(x.OK()); } } // identities for equal-length args void identitytest(BitString a, BitString b, BitString c) { // neg assert(~(~a) == a); // commutative assert((a | b) == (b | a)); assert((a & b) == (b & a)); // associative assert((a | (b | c)) == ((a | b) | c)); assert((a & (b & c)) == ((a & b) & c)); // distrib assert((a & (b | c)) == ((a & b) | (a & c))); assert((a | (b & c)) == ((a | b) & (a | c))); // absorption assert((a & (a | b)) == a); assert((a | (a & b)) == a); // demorgan assert((a | b) == ~(~a & ~b)); assert((a & b) == ~(~a | ~b)); // def of - assert((a - b) == (a & ~b)); assert(((a - b) | b) == (a | b)); // def of disjoint union assert((a ^ b) == ((a | b) & ~(a & b))); assert((a ^ b) == ((a - b) | (b - a))); // shift assert(((a << 1) >> 1) == a); // concat assert((a + (b + c)) == ((a + b) + c)); BitString x; x = a + b; assert(x.after(a) == b); assert(x.before(b, -1) == a); x = a; int l = x.length(); x.set(l); assert(x == (a + 1)); x.clear(l); assert(x == (a + 0)); } void accumtest(BitString& a, BitString& b, BitString& c) { BitString x = a; x &= b; assert(x == (a & b)); x |= c; assert(x == ((a & b) | c)); x -= a; assert(x == (((a & b) | c) - a)); x ^= b; assert(x == ((((a & b) | c) - a) ^ b)); x += c; assert(x == (((((a & b) | c) - a) ^ b) + c)); x <<= 7; assert(x == ((((((a & b) | c) - a) ^ b) + c) << 7)); x >>= 5; assert(x == (((((((a & b) | c) - a) ^ b) + c) << 7) >> 5)); x += 0; assert(x == ((((((((a & b) | c) - a) ^ b) + c) << 7) >> 5) + 0)); assert(x.OK()); } void cmptest(BitString& x) { BitString a = x; a[0] = 0; BitString b = a; assert(a == b); assert(a <= b); assert(a >= b); assert(!(a != b)); assert(!(a > b)); assert(!(a < b)); assert(lcompare(a, b) == 0); assert(a.matches(b)); assert(a.contains(b)); b[0] = 1; cout << "b.set(0) :" << b << "\n"; assert(!(a == b)); assert(!(a >= b)); assert(!(a > b)); assert((a != b)); assert(a <= b); assert((a < b)); assert(lcompare(a, b) < 0); assert(!a.matches(b)); assert(!a.contains(b)); assert(a.after(0) == b.after(0)); b.set(65); cout << "b.set(65):\n" << b << "\n"; assert(b[65] == 1); assert(b[64] == 0); assert(b.length() == 66); b.clear(2); cout << "b.clear(2):\n" << b << "\n"; assert(b[2] == 0); b.set(11); b.invert(11,20); cout << "b.invert(11,20):\n" << b << "\n"; assert(b[11] == 0); b.set(21,30); cout << "b.set(21,30):\n" << b << "\n"; assert(b[21] == 1); b.clear(31,40); cout << "b.clear(31, 40):\n" << b << "\n"; assert(b.test(33, 38) == 0); } void subtest(BitString c) { BitString k = c.at(1, 4); cout << "k = " << k << "\n"; assert(c.index(k) == 1); assert(c.index(k, -1) != -1); cout << "c.before(k) = " << c.before(k) << "\n"; assert(c.before(k) == c.before(1)); cout << "c.at(k) = " << c.at(k) << "\n"; assert(c.at(k) == k); cout << "c.after(k) = " << c.after(k) << "\n"; assert(c.after(k) == c.after(4)); c.after(k) = k; cout << "c.after(k)=k :" << c << "\n"; assert(c.after(4) == k); c.before(k) = k; cout << "c.before(k)=k:" << c << "\n"; assert(c.after(c.after(k)) == k); assert(c.contains(k, 0)); assert(common_prefix(c, k) == k); assert(common_suffix(c, k) == k); cout << "reverse(k) = " << reverse(k) << "\n"; k.left_trim(0); assert(k[0] == 1); cout << "k.left_trim(0) : " << k << "\n"; k.right_trim(1); assert(k[k.length() - 1] == 0); cout << "k.right_trim(1) : " << k << "\n"; } main() { BitString a; BitString b = atoBitString("1000000001"); BitString c = atoBitString("10101010101010101010"); BitString d = atoBitString("00110011001100110011"); BitString e = atoBitString("11110000111100001111"); BitString f = b; BitString g = ~e; BitString h = d; assert(a.OK()); assert(a.empty()); assert(b.OK()); assert(!b.empty()); assert(c.OK()); assert(c.count(1) == 10); assert(c.count(0) == 10); assert(d.OK()); assert(c.count(1) == 10); assert(c.count(0) == 10); assert(e.OK()); assert(e.count(1) == 12); assert(e.count(0) == 8); assert(f == b); assert(h == d); assert(g == ~e); assert(~g == e); assert(f.OK()); assert(g.OK()); assert(h.OK()); cout << "a = " << a << "\n"; cout << "b = " << b << "\n"; cout << "c = " << c << "\n"; cout << "d = " << d << "\n"; cout << "e = " << e << "\n"; cout << "f = b = " << f << "\n"; cout << "g = ~e = " << g << "\n"; cout << "h = d = " << h << "\n"; for (int i = 0; i < 20; ++i) { assert(h[i] == d[i]); assert(g[i] != e[i]); assert(c[i] == !(i % 2)); } cout << "bits in e:\n"; for (int p = e.first(); p >= 0; p = e.next(p)) { assert(e[p] == 1); cout << p << " "; } cout << "\n"; cout << "clear bits in g (reverse order):\n"; for (p = g.last(0); p >= 0; p = g.previous(p, 0)) { assert(g[p] == 0); cout << p << " "; } cout << "\n"; cout << "~c = " << (~c) << "\n"; cout << "c & d = " << (c & d) << "\n"; cout << "c | d = " << (c | d) << "\n"; cout << "c - d = " << (c - d) << "\n"; cout << "c ^ d = " << (c ^ d) << "\n"; cout << "c + d = " << (c + d) << "\n"; cout << "c <<2 = " << (c << 2) << "\n"; cout << "c >>2 = " << (c >> 2) << "\n"; f &= c; cout << "f &= c = " << f << "\n"; f |= d; cout << "f |= d = " << f << "\n"; f -= d; cout << "f -= e = " << f << "\n"; f ^= c; cout << "f ^= c = " << f << "\n"; f += b; cout << "f += b = " << f << "\n"; f <<= 5; cout << "f <<=5 = " << f << "\n"; f >>= 10; cout << "f >>=10= " << f << "\n"; assert(c != d); assert(!(c == d)); assert(!(c < d)); assert(!(c > d)); assert(!(c <= d)); assert(!(c >= d)); assert(lcompare(c, d) > 0); BitString l = c + d + c; cout << "l = " << l << "\n"; BitPattern pat(d, e); assert(pat.OK()); cout << "BitPattern pat = " << pat << "\n"; cout << "pat.pattern = " << pat.pattern << "\n"; cout << "pat.mask = " << pat.mask << "\n"; assert(d.matches(pat)); cout << "l.index(pat) = " << l.index(pat) << "\n"; cout << "l.index(pat,-1)= " << l.index(pat, -1) << "\n"; cout << "l.before(pat) = " << l.before(pat) << "\n"; cout << "l.at(pat) = " << l.at(pat) << "\n"; cout << "l.after(pat) = " << l.after(pat) << "\n"; int eind = l.index(pat); l.at(pat) = e; assert(l.index(e) == eind); identitytest(d, g, h); identitytest(a, a, a); identitytest(c, d, e); identitytest(e, d, c); identitytest(longtoBitString(0), longtoBitString((unsigned)(~(0L))), shorttoBitString(1025)); identitytest(a+b+c+d+e+f+g+h, h+g+f+e+d+c+b+a, a+c+e+g+b+d+f+h); accumtest(d, g, h); accumtest(a, b, c); accumtest(c, d, e); accumtest(e, d, c); accumtest(a+b+c+d+e+f+g+h+l, f+e+d+c+b+a+pat.mask, e+g+b+d+f+h+pat.pattern); doubletest(a); doubletest(b); doubletest(c); doubletest(a+b+c+d+e+f+g+h); cmptest(b); cmptest(d); subtest(c); subtest(d); cout << "\nEnd of test.\n"; } st(longtoBitString(0), longtoBitString((unsigned)(~(0L))), shorttoBitString(1025)); identitlibg++/tests/tPlex.cc 644 473 0 31501 4677700037 7725 /* test of Plexes */ #include #include #include "iPlex.h" #define tassert(ex) {if ((ex)) cerr << #ex << "\n"; \ else _assert(#ex, __FILE__,__LINE__); } void printplex(intPlex& a) { cout << "["; int maxprint = 20; int k = 0; for (int i = a.low(); i < a.fence() && k < maxprint; ++i, ++k) cout << a[i] << " "; if (i < a.fence()) cout << "]\n"; else cout << "...]\n"; } #include "iFPlex.h" void FPtest () { intFPlex p(50); assert(p.OK()); assert (p.empty()); p.add_high (1000); Pix px = p.index_to_Pix(0); assert (p.length() == 1); assert(p.owns(px)); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 0); p.reset_low (10); assert (p.length() == 1); assert (p.low() == 10); assert (p[10] == 1000); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 10); assert(p.index_to_Pix(10) == px); assert(p.OK()); int h = p.high_element(); int l = p.low_element(); assert ( (h==l) && (h==1000)); p.fill(222); assert(p(px) == 222); p.del_high(); assert(p.empty()); assert(!p.owns(px)); intFPlex q(10, -50); q.add_low (-1000); assert (q[9] == -1000); q[9] = 21; assert(!q.valid(10)); assert(q.OK()); q.del_low(); assert (q.empty()); p.reset_low (0); q.reset_low (0); for (int i = 0; i < 50; i++) { if (i % 2 == 0) { p.add_high (i); assert (p.high() == i/2); p[i/2] = p[i/4]; assert (p.high_element() == i/4); p[i/2] = i/2; } else { q.add_low (-i); int ii = - (i/2) -1; assert (q.low() == ii); q.low_element() = ii; assert (q[ii] == ii); } } cout << "q:"; printplex(q); assert (p.length() == 25); assert (q.length() == 25); assert(p.valid(0)); assert(p.owns(px)); px = p.first(); i = 0; for (int it1 = p.low(); it1 < p.fence(); p.next(it1)) { assert (p[it1] == it1); assert(p(px) == p[it1]); p.next(px); ++i; } assert(px == 0); px = q.last(); for (it1 = q.high(); it1 > q.ecnef(); q.prev(it1)) { assert (q[it1] == it1); assert(p(px) == q[it1]); q.prev(px); ++i; } assert(i == 50); q.reset_low (0); assert (p.high() == q.high()); assert(p.low() == 0); intFPlex p1 = p; intFPlex p2 (p); intFPlex p3 = p2; assert (p1.length() == 25); assert (p1.high() == 24); assert(p1.low() == 0); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); i = 0; for (int it5 = p.low(); it5 < p.fence(); p.next(it5)) { assert(p1.low() == it5); p1.del_low(); assert(!p1.valid(it5)); p2.del_high (); p3 [it5] = -it5; ++i; } assert(i == 25); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); assert (p1.empty()); assert (p2.empty()); p3.append (p); assert(p3.OK()); p1.prepend (p); p2.append (p); assert(p1.length() == p.length()); assert(p1.length() == p2.length()); assert(p1.OK()); assert(p2.OK()); p2.clear(); assert(p2.OK()); assert(p2.empty()); p2 = p1; assert(p2.OK()); p1 = p; assert(p1.OK()); p1.reset_low (p1.low_element()); for (int it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == it6); } p1[13] = 1313; p1[7] = -7777; p1[24] = 24242424; assert(!p1.valid(25)); assert(!p1.valid(-1)); assert(p1.OK()); } #include "iXPlex.h" void XPtest () { intXPlex p(3); assert(p.OK()); assert (p.empty()); p.add_high (1000); Pix px = p.index_to_Pix(0); assert(p.Pix_to_index(px) == 0); assert (p.length() == 1); assert(p.owns(px)); assert(p(px) == 1000); p.reset_low(10); assert (p.length() == 1); assert (p.low() == 10); assert (p[10] == 1000); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 10); assert(p.index_to_Pix(10) == px); assert(p.OK()); int h = p.high_element(); int l = p.low_element(); assert ( (h==l) && (h==1000)); p.fill(222); assert(p(px) == 222); p.del_high(); assert(p.empty()); assert(!p.owns(px)); p.add_low(-1000); assert (p[9] == -1000); p[9] = 21; assert(!p.valid(10)); assert(p.OK()); p.del_low(); assert (p.empty()); p.reset_low (0); for (int i = 0; i < 50; i++) { if (i % 2 == 0) { p.add_high (i); assert (p.high() == i/2); p[i/2] = p[i/4]; assert (p.high_element() == i/4); p[i/2] = i/2; } else { p.add_low (-i); int ii = - (i/2) -1; assert (p.low() == ii); p.low_element() = ii; assert (p[ii] == ii); } } assert (p.length() == 50); cout << "p:"; printplex(p); assert(p.valid(0)); assert(p.owns(px)); px = p.first(); i = 0; for (int it1 = p.low(); it1 < p.fence(); p.next(it1)) { assert (p[it1] == it1); assert(p(px) == p[it1]); p.next(px); ++i; } assert(i == 50); assert(px == 0); p.reset_low (0); assert (p.high() == 49); assert(p.low() == 0); i = 0; for (int it2 = p.high(); it2 > p.ecnef(); p.prev(it2)) { assert ( p[it2] == it2-25 ); ++i; } assert(i == 50); assert(p.OK()); intXPlex p1 = p; intXPlex p2 (p); intXPlex p3 = p2; assert (p1.length() == 50); assert (p1.high() == 49); assert(p1.low() == 0); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); i = 0; for (int it5 = p.low(); it5 < p.fence(); p.next(it5)) { assert(p1.low() == it5); p1.del_low(); assert(!p1.valid(it5)); p2.del_high (); p3 [it5] = -it5; ++i; } assert(i == 50); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); assert (p1.empty()); assert (p2.empty()); p3.append (p); assert(p3.OK()); p1.prepend (p); p2.append (p); assert(p1.length() == p.length()); assert(p1.length() == p2.length()); assert(p1.OK()); assert(p2.OK()); p2.clear(); assert(p2.OK()); assert(p2.empty()); p2 = p1; assert(p2.OK()); p1 = p; assert(p1.OK()); p1.reset_low(p1.low_element()); p1 [13] = 1313; p1 [-7] = -7777; p1 [-25] = -252525; p1 [24] = 24242424; assert(!p1.valid(25)); assert(!p1.valid(-26)); assert(p1.OK()); p1 = p; p1.reset_low (p1.low_element()); for (int it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == it6); } p1.reverse(); i = p1.high(); for (it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == i); --i; } assert(p1.OK()); } #include "iMPlex.h" void MPtest () { intMPlex p(3); assert(p.OK()); assert (p.empty()); p.add_high (1000); Pix px = p.index_to_Pix(0); assert (p.length() == 1); assert(p.owns(px)); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 0); p.reset_low (10); assert (p.length() == 1); assert (p.low() == 10); assert (p[10] == 1000); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 10); assert(p.index_to_Pix(10) == px); assert(p.OK()); int h = p.high_element(); int l = p.low_element(); assert ( (h==l) && (h==1000)); p.fill(222); assert(p(px) == 222); p.del_high(); assert(p.empty()); assert(!p.owns(px)); p.add_low (-1000); assert (p[9] == -1000); p[9] = 21; assert(!p.valid(10)); assert(p.OK()); p.del_low(); assert (p.empty()); p.reset_low (0); for (int i = 0; i < 50; i++) { if (i % 2 == 0) { p.add_high (i); assert (p.high() == i/2); p[i/2] = p[i/4]; assert (p.high_element() == i/4); p[i/2] = i/2; } else { p.add_low (-i); int ii = - (i/2) -1; assert (p.low() == ii); p.low_element() = ii; assert (p[ii] == ii); } } cout << "p:"; printplex(p); assert (p.length() == 50); assert (p.count() == 50); assert(p.available() == 0); assert(p.valid(0)); px = &p[0]; assert(p.owns(px)); p.del_index(0); assert(p.count() == 49); assert(p.available() == 1); assert(p.unused_index() == 0); assert(!p.valid(0)); assert(!p.owns(px)); p.undel_index(0); p[0] = 0; assert(p.count() == 50); assert(p.available() == 0); assert(p.valid(0)); assert(p.owns(px)); assert(p.OK()); p.del_index(0); px = p.first(); i = 0; for (int it1 = p.low(); it1 < p.fence(); p.next(it1)) { assert (p[it1] == it1); assert(p(px) == p[it1]); p.next(px); ++i; } assert(i == 49); assert(px == 0); p.reset_low (0); assert (p.high() == 49); assert(p.low() == 0); i = 0; for (int it2 = p.high(); it2 > p.ecnef(); p.prev(it2)) { assert ( p[it2] == it2-25 ); assert(px != &p[it2]); ++i; } assert(i == 49); assert(p.OK()); p.del_index(1); p.del_index(2); assert (p.OK()); assert (p.count() == 47); intMPlex p1 = p; intMPlex p2 (p); intMPlex p3 = p2; assert (p1.length() == 50); assert (p1.count() == 47); assert (p1.high() == 49); assert(p1.low() == 0); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); i = 0; for (int it5 = p.low(); it5 < p.fence(); p.next(it5)) { assert(p1.low() == it5); p1.del_low(); assert(!p1.valid(it5)); p2.del_high (); p3 [it5] = -it5; ++i; } assert(i == 47); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); assert (p1.empty()); assert (p2.empty()); p3.append (p); assert(p3.OK()); p1.prepend (p); p2.append (p); assert(p1.count() == p.count()); assert(p1.count() == p2.count()); assert(p1.OK()); assert(p2.OK()); p2.clear(); assert(p2.OK()); assert(p2.empty()); p2 = p1; assert(p2.OK()); p1 = p; p1.del_index(3); p1.del_index(4); p1.del_index(5); p1.del_index(6); p1.del_index(7); p1.del_index(8); p1.undel_index(6); p1[6] = 6666; p1[9] = 9999; p1[0] = 0; assert(p1[6] == 6666); assert(!p1.valid(5)); assert(!p1.valid(7)); p1.del_low(); assert(p1.low() == 6); assert(p1.OK()); } #include "iRPlex.h" void RPtest () { intRPlex p(3); assert(p.OK()); assert (p.empty()); p.add_high (1000); Pix px = p.index_to_Pix(0); assert(p.Pix_to_index(px) == 0); assert (p.length() == 1); assert(p.owns(px)); assert(p(px) == 1000); p.reset_low(10); assert (p.length() == 1); assert (p.low() == 10); assert (p[10] == 1000); assert(p(px) == 1000); assert(p.Pix_to_index(px) == 10); assert(p.index_to_Pix(10) == px); assert(p.OK()); int h = p.high_element(); int l = p.low_element(); assert ( (h==l) && (h==1000)); p.fill(222); assert(p(px) == 222); p.del_high(); assert(p.empty()); assert(!p.owns(px)); p.add_low(-1000); assert (p[9] == -1000); p[9] = 21; assert(!p.valid(10)); assert(p.OK()); p.del_low(); assert (p.empty()); p.reset_low (0); for (int i = 0; i < 50; i++) { if (i % 2 == 0) { p.add_high (i); assert (p.high() == i/2); p[i/2] = p[i/4]; assert (p.high_element() == i/4); p[i/2] = i/2; } else { p.add_low (-i); int ii = - (i/2) -1; assert (p.low() == ii); p.low_element() = ii; assert (p[ii] == ii); } } assert (p.length() == 50); cout << "p:"; printplex(p); assert(p.valid(0)); assert(p.owns(px)); px = p.first(); i = 0; for (int it1 = p.low(); it1 < p.fence(); p.next(it1)) { assert (p[it1] == it1); assert(p(px) == p[it1]); p.next(px); ++i; } assert(i == 50); assert(px == 0); p.reset_low (0); assert (p.high() == 49); assert(p.low() == 0); i = 0; for (int it2 = p.high(); it2 > p.ecnef(); p.prev(it2)) { assert ( p[it2] == it2-25 ); ++i; } assert(i == 50); assert(p.OK()); intRPlex p1 = p; intRPlex p2 (p); intRPlex p3 = p2; assert (p1.length() == 50); assert (p1.high() == 49); assert(p1.low() == 0); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); i = 0; for (int it5 = p.low(); it5 < p.fence(); p.next(it5)) { assert(p1.low() == it5); p1.del_low(); assert(!p1.valid(it5)); p2.del_high (); p3 [it5] = -it5; ++i; } assert(i == 50); assert(p.OK()); assert(p1.OK()); assert(p2.OK()); assert(p3.OK()); assert (p1.empty()); assert (p2.empty()); p3.append (p); assert(p3.OK()); p1.prepend (p); p2.append (p); assert(p1.length() == p.length()); assert(p1.length() == p2.length()); assert(p1.OK()); assert(p2.OK()); p2.clear(); assert(p2.OK()); assert(p2.empty()); p2 = p1; assert(p2.OK()); p1 = p; assert(p1.OK()); p1.reset_low(p1.low_element()); p1 [13] = 1313; p1 [-7] = -7777; p1 [-25] = -252525; p1 [24] = 24242424; assert(!p1.valid(25)); assert(!p1.valid(-26)); assert(p1.OK()); p1 = p; p1.reset_low (p1.low_element()); for (int it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == it6); } p1.reverse(); i = p1.high(); for (it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == i); --i; } assert(p1.OK()); } main() { cout << "FPtest\n"; FPtest(); cout << "XPtest\n"; XPtest(); cout << "MPtest\n"; MPtest(); cout << "RPtest\n"; RPtest(); cout << "\nend of tests\n"; } 1.valid(25)); assert(!p1.valid(-26)); assert(p1.OK()); p1 = p; p1.reset_low (p1.low_element()); for (int it6 = p1.low(); it6 < p1.fence(); it6++) { assert (p1[it6] == it6); libg++/tests/tVec.cc 644 473 0 4067 4677700037 7521 /* test/demo of Vecs, AVecs */ #include #include "iVec.h" #include "iAVec.h" int int_compare(int a, int b) { return a - b; } int plus(int a, int b) { return a + b; } int inc(int a) { return a + 1; } void printint(int a) { cout << a << " "; } void print(intVec& a) { a.apply(printint); cout << "\n"; } #include MLCG randgen; main() { intVec a(20); for (int i = 0; i < a.capacity(); ++i) a[i] = randgen.asLong() % 100; cout << "a: "; print(a); a.sort(int_compare); cout << "a.sort():"; print(a); intVec b = map(inc, a); cout << "b = map(inc, a): "; print(b); intVec c = merge(a, b, int_compare); cout << "c = merge(a, b): "; print(c); intVec d = concat(a, b); cout << "d = concat(a, b): "; print(d); d.resize(10); cout << "d.resize(10): "; print(d); d.reverse(); cout << "d.reverse(): "; print(d); d.fill(0, 4, 4); cout << "d.fill(0, 4, 4): "; print(d); cout << "d.reduce(plus, 0) = " << d.reduce(plus, 0) << "\n"; intVec e = d.at(2, 5); cout << "e = d.at(2, 5): "; print(e); intAVec x(20); for (i = 0; i < x.capacity(); ++i) x[i] = i; cout << "x: "; print(x); intAVec y(20); for (i = 0; i < y.capacity(); ++i) y[i] = randgen.asLong() % 100 + 1; cout << "y: "; print(y); cout << "x + y: "; print(x + y); cout << "x - y: "; print(x - y); cout << "product(x, y): "; print(product(x,y)); cout << "quotient(x, y): "; print(quotient(x,y)); cout << "x * y: " << (x * y) << "\n"; cout << "x + 2: "; print(x + 2); cout << "x - 2: "; print(x - 2); cout << "x * 2: "; print(x * 2); cout << "x / 2: "; print(x / 2); intAVec z(20, 1); cout << "z(20, 1): "; print(z); cout << "z = -z: "; print(z = -z); cout << "z += x: "; print(z += x); cout << "z -= x: "; print(z -= x); cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << x.max_index() << "\n"; cout << "\nEnd of test\n"; } cout << "x / 2: "; print(x / 2); intAVec z(20, 1); cout << "z(20, 1): "; print(z); cout << "z = -z: "; print(z = -z); cout << "z += x: "; print(z += x); cout << "z -= x: "; print(z -= x); cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tSet.inp 644 473 0 0 4677700037 7637 libg++/tests/tPlex.inp 644 473 0 0 4677700037 10014 libg++/tests/test0.inp 644 473 0 11 4677700040 7773 bye bye2 ex() << "\n"; cout << "\nEnd of test\n"; } cout << "x / 2: "; print(x / 2); intAVec z(20, 1); cout << "z(20, 1): "; print(z); cout << "z = -z: "; print(z = -z); cout << "z += x: "; print(z += x); cout << "z -= x: "; print(z -= x); cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tFile.inp 644 473 0 53 4677700040 10005 a 123 4567 89012 123.456 -1.2e-2 1 2 3 4 5 test\n"; } cout << "x / 2: "; print(x / 2); intAVec z(20, 1); cout << "z(20, 1): "; print(z); cout << "z = -z: "; print(z = -z); cout << "z += x: "; print(z += x); cout << "z -= x: "; print(z -= x); cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tBag.inp 644 473 0 0 4677700040 7567 libg++/tests/tObstack.inp 644 473 0 401 4677700040 10531 This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tString.inp 644 473 0 33 4677700040 10372 abcdefghijklmnopqrstuvwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tInteger.inp 644 473 0 25 4677700040 10522 12345678901234567890 vwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tRational.inp 644 473 0 23 4677700041 10675 123455678/98765432 0 vwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tGetOpt.inp 644 473 0 0 4677700041 10301 libg++/tests/tComplex.inp 644 473 0 13 4677700041 10532 (1.2, -34) 8765432 0 vwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/twrapper.inp 644 473 0 24 4677700041 10605 10 20 30 30 20 10 0 vwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/tgwrapper.inp 644 473 0 24 4677700041 10754 10 20 30 30 20 10 0 vwxyz for Obstacks The test program should simply list the words in this file with redundant words deleted This is a simple test file for Obstacks The test program should simply list the words in this file with redundant words deleted cout << "x.sum(): " << x.sum() << "\n"; cout << "x.sumsq(): " << x.sumsq() << "\n"; cout << "x.min(): " << x.min() << "\n"; cout << "x.max(): " << x.max() << "\n"; cout << "x.min_index(): " << x.min_index() << "\n"; cout << "x.max_index(): " << libg++/tests/expected.out 644 473 0 112335 4677700042 10675 Must run test0 from tty tFile Hello, world via cout Hello, world via cerr enter a char:c = "a" enter three integers (short, int, long):first = 123 via dec = 123 second = 4567 via form = 4567 = 010727 via cout.form = 4567 = 0x11d7 third = 89012 via hex = 15bb4 enter a float then a double:first = 123.456 second = -0.012 enter 5 characters separated with spaces:first = 1 rest = 2 3 4 5 Making streams sout and sin...contents of file: Thisfilehasonelinetestingoutputstreams. Making File tf ... first line of file: This is the first and only line of this file. next char = 10 reopening tempfile, appending: Now there is a second line. First 10 chars via raw system read after reopen for input: This is th Contents after raw lseek to pos 5: is the first and only line of this file. Now there is a second line. Making SFile rf...odd elements of file in reverse order: (i = 9 c = j d = 0.009) (i = 7 c = h d = 0.007) (i = 5 c = f d = 0.005) (i = 3 c = d d = 0.003) (i = 1 c = b d = 0.001) Making PlotFile pf ...(You may delete or attempt to plot plot.out) creating string-based ostream... with contents: This is a string-based stream. With two lines. using it to create string-based istream... with contents: This is a string-based stream. With two lines. Making filebuf streams fout and fin...contents of file: Thisfilehasonelinetestingoutputstreams. The following file open should generate error message: error in File shouldnotexist: No such file or directory Final names & states: cin: (stdin) 0 cout: (stdout) 0 cerr: (stderr) 0 end of test. tObstack enter anything at all, end with an EOF(^D) unique words: deleted redundant with this in words the list simply should program The Obstacks for file test simple a is This Obstack vars: alignment_mask = 3 chunk_size = 4080 size = 0 room = 4056 end of test tString an empty String: A string initialized to Hello:Hello A string initialized to previous string:Hello A string initialized to previous string.at(1, 2):el A string initialized to @:@ A string initialized to dec(20):20 n = 20 atoi(n) = 20 atof(n) = 20 z = x + y = Helloworld x += y; x = Helloworld y.prepend(x); y = Helloworld cat(x, y, x, x); x = HelloworldHello cat(y, x, x, x); x = worldHelloHello z = x + s + + y.at(w) + y.after(w) + . = Hello, world. ch = x[0] = H z = x.at(2, 3) = llo x.at(2, 2) = r; x = Hero x.at(0, 1) = j; x = jello x.at(He) = je; x = jello x.at(l, -1) = i; x = Helio z = x.at(r) = ello z = x.before(o) = Hell x.before(ll) = Bri; x = Brillo z = x.before(2) = He z = x.after(Hel) = lo x.after(Hel) = p; x = Help z = x.after(3) = o z = a bc; z = z.after(RXwhite); z =a bc x.gsub(l, ll); x = Hellllo x.gsub(r, ...); x = Hello should have been replaced by this string x.gsub(RXwhite, #); x = Hello#should#have#been#replaced#by#this#string z = x+y; z.del(loworl); z = Held reverse(x) = olleH x.reverse() = olleH upcase(x) = HELLO downcase(x) = hello capitalize(x) = Hello z = replicate(*, 10) = ********** z = This string has five words from split(z, RXwhite, w, 10), n words = 5: This string has five words z = join(w, nw, /); z =This/string/has/five/words enter a word:word =abcdefghijklmnopqrstuvwxyz length = 26 End of test tInteger one = 1 one + 1 = 2 two = 2 fact30 = factorial(30) = 265252859812191058636308480000000 fact28 = factorial(28) = 304888344611713860501504000000 fact30 + fact28 = 265557748156802772496809984000000 fact30 - fact28 = 264947971467579344775806976000000 fact30 * fact28 = 80872505331661933764010628483512781121876047953920000000000000 fact30 / fact28 = 870 fact30 % fact28 = 0 -fact30 = -265252859812191058636308480000000 lg(fact30) = 107 gcd(fact30, fact28) = 304888344611713860501504000000 sqrt(fact30) = 16286585271694955 negfact31 = -8222838654177922817725562880000000 fact30 + negfact31 = -7957585794365731759089254400000000 fact30 - negfact31 = 8488091513990113876361871360000000 fact30 * negfact31 = -2181131468794922353615366650200339706856997013317222400000000000000 fact30 / negfact31 = 0 fact30 % negfact31 = 265252859812191058636308480000000 gcd(fact30, negfact31) = 265252859812191058636308480000000 fib50 = fibonacci(50) = 12586269025 fib48 = fibonacci(48) = 4807526976 fib48 + fib50 = 17393796001 fib48 - fib50 = -7778742049 fib48 * fib50 = 60508827864880718400 fib48 / fib50 = 0 fib48 % fib50 = 4807526976 gcd(fib50, fib48) = 1 sqrt(fib50) = 112188 pow64 = Ipow(2, 64) = 18446744073709551616 lg(pow64) = 64 s64 = 1 << 64 = 18446744073709551616 s32 = s64 >> 32 = 4294967296 comps64 = ~s64 = 18446744073709551615 comps64 & s32 = 4294967296 comps64 | s32 = 18446744073709551615 comps64 ^ s32 = 18446744069414584319 enter an Integer: number = 12345678901234567890 End of test twrapper memoizing with table size 10 Number: 10! = 3628800 Number: 20! = 2432902008176640000 Number: 30! = 265252859812191058636308480000000 Number: 30! = 265252859812191058636308480000000 Number: 20! = 2432902008176640000 Number: 10! = 3628800 Number: bye! tgwrapper memoizing with table size 10 Number: 10! = 3628800 Number: 20! = 2432902008176640000 Number: 30! = 265252859812191058636308480000000 Number: 30! = 265252859812191058636308480000000 Number: 20! = 2432902008176640000 Number: 10! = 3628800 Number: bye! tRational one = 1 third = 1/3 half = 1/2 third + half = 5/6 third - half = -1/6 third * half = 1/6 third / half = 2/3 onePointTwo = 5404319552844595/4503599627370496 double(onePointTwo) = 1.2 a = 1 a += half = 3/2 a -= half = 1 a *= half = 1/2 a /= half = 1 approxpi = 355/113 double(approxpi) = 3.14159 rpi = Rational(PI) = 884279719003555/281474976710656 double(rpi) = 3.14159 approxpi + rpi = 199847224979684595/31806672368304128 approxpi - rpi = 8484881165/31806672368304128 approxpi * rpi = 313919300246262025/31806672368304128 approxpi / rpi = 19984723346456576/19984721649480343 -approxpi = -355/113 abs(negapproxpi) = 355/113 enter a Rational in form a/b or a: number = 61727839/49382716 approximating e as pow(1+1/n),n) for n =10 double(approxe) = 2.59374 log(approxe) = .953102 approxe = 25937424601/10000000000 approximating e as pow(1+1/n),n) for n =100 double(approxe) = 2.70481 log(approxe) = .995033 approxe = 270481382942152609326719471080753083367793838278100277689020104911710151430673927943945601434674459097335651375483564268312519281766832427980496322329650055217977882315938008175933291885667484249510001/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 approximating e as pow(1+1/n),n) for n =1000 double(approxe) = 2.71692 log(approxe) = 0.9995 approxe = 2716923932235892457383088121947577188964315018836572803722354774868894945523768158997885697298661429053421034015406256924859461187617653889457753593083386399572063538500432650176144488046171044844121805479607648086607018742077798375087855857012278053105042704758822511824867218226931719410407150364389665913091822576819072281835735365786202176167228686198158460724641052407506305826211156964723064441295969498221919251479211700941935114755531972677360157561485144237786816579422141378066423317811515462669946309306263409027388915931082226854264858661420878279983534424128672461206356847463821364630504359665171573635397346037274752410368174877433941234543153511100471651472869116068528478976916600585383497180172395573924789047989563714318957536493108041591460911612078698461739084741934442448701416575483263891529095158013233115648534154086009312190489168546024398834243847135102411661996020129557921444666343641039137906807591342742464200991933722791531063202677650581946360422027765645970182463780273161113009717582155489902677095053354207944772439271656447869921825959042801322775729022491402012084605367784456090892987682547811360481731795980637847551788259384243997341190753089343387201753821360405430310320564488741142120089460368986590136324737459372963666586532443570474179352656517635333744783401695951969936296323256525034685525470426185224036844803487442831639483152362831735350269624668701702424450940840884555271325190876102665277858154695092765613639718577127438538649414492678358762110235621776218781360881010654696273264706319088453035858355052988808507775439561385232652305316287705653436727647681405618323757201022946801118770148072424021385261829594248369890171583993147934044232792517118743393217276416179842097554494269012251329134783596037733973478306188255291484352384699871420472711423079586319041837563678498472779422282261024744394844558738378027105699691260086532632930941478779680554645850778168703661423819000515895232903243738763481571999080702098369316199601942246247887808385073821861517636839926907458184604648942036355256683219218129910422822177336785268627274482037476294341444562207197209503659518266210432791078248321015453218019586608696207295299183111963158564162419152742807437346241667671688466998244424726765837682151606230638111654756595917019206453978024157097042546937345673337179165242325399648121877178987723999503839197328183925340949191821443698275476295245249466361817367207248089144718808572152781037112209285944844021186534832159964297181970584453756163204297111185823467744743465840230098261424789313315093951766314459027947176701489215746884363426961577348384651887153140609616362927338107686794499974902581579897076172716541504294334300741444106749994715713419630688719451362658288812132056854807330827050505064714442618243101018812153563795539024370219967801515099970721926240625418512417940854760415566229746248973756297569452302821563467574313259066016089521122779204844875998864114930516063910324359331903843040069467324167490917499501000001/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 End of test tComplex Complex one = (1, 0) i = (0, 1) neg_one = (-1, 0) sqrt(neg_one) = (0, 1) a = (2, 3) b = (4, 5) a + one = (3, 3) a - one = (1, 3) a * one = (2, 3) a / one = (2, 3) a + b = (6, 8) a - b = (-2, -2) a * b = (-7, 22) a / b = (.560976, 0.04878) c = a; c += b = (6, 8) c = a; c -= b = (-2, -2) c = a; c *= b = (-7, 22) c = a; c /= b = (.560976, 0.04878) -a = (-2, -3) real(a) = 2 imag(a) = 3 conj(a) = (2, -3) norm(a) = 13 abs(a) = 3.60555 arg(a) = .982794 cos(a) = (-4.18963, -9.10923) sin(a) = (9.15450, -4.16891) cosh(a) = (-3.72455, .511823) sinh(a) = (-3.59056, .530921) log(a) = (1.28247, .982794) exp(a) = (-7.31511, 1.04274) sqrt(a) = (1.67415, .895977) pow(a, 2) = (-5, 12) pow(a, b) = (33.8367, -165.578) enter a Complex number in form (a, b) or (a) or a: number = (1.2, -34) End of test tBitSet BitSet tests: a = 0* b = 000000000010* c = 1010101010101010101010101010101010101010* c[0] =1 c[1] =0 c[2] =1 c[3] =0 c[4] =1 d = 00110011001100110011001100110011001100110* e = 1111000011110000111100001111000011110* u = ~a = 1* g = ~e = 0000111100001111000011110000111100001* ~c = 0101010101010101010101010101010101010101* c & d = 0010001000100010001000100010001000100010* c | d = 10111011101110111011101110111011101110110* c - d = 10001000100010001000100010001000100010* c ^ d = 10011001100110011001100110011001100110010* f = b = 100000000010* f &= c = 100000000010* f |= d = 10110011001100110011001100110011001100110* f -= e = 00000011000000110000001100000011000000110* f ^= u = 11111100111111001111110011111100111111001* h = d :00110011001100110011001100110011001100110* h.set(0): 10110011001100110011001100110011001100110* h.set(65): 1011001100110011001100110011001100110011000000000000000000000000010* h.clear(2): 1001001100110011001100110011001100110011000000000000000000000000010* h.invert(11,20): 1001001100101100110010110011001100110011000000000000000000000000010* h.set(21,30): 1001001100101100110011111111111100110011000000000000000000000000010* h.clear(31, 40): 1001001100101100110011111111111000000000000000000000000000000000010* h.test(0,5) = 1 h.test(31,40) = 0 set bits in e: 0 1 2 3 8 9 10 11 16 17 18 19 24 25 26 27 32 33 34 35 clear bits in g (reverse order): 35 34 33 32 27 26 25 24 19 18 17 16 11 10 9 8 3 2 1 0 End of test. tBitString a = b = 1000000001 c = 10101010101010101010 d = 00110011001100110011 e = 11110000111100001111 f = b = 1000000001 g = ~e = 00001111000011110000 h = d = 00110011001100110011 bits in e: 0 1 2 3 8 9 10 11 16 17 18 19 clear bits in g (reverse order): 19 18 17 16 11 10 9 8 3 2 1 0 ~c = 01010101010101010101 c & d = 00100010001000100010 c | d = 10111011101110111011 c - d = 10001000100010001000 c ^ d = 10011001100110011001 c + d = 1010101010101010101000110011001100110011 c <<2 = 0010101010101010101010 c >>2 = 101010101010101010 f &= c = 1000000000 f |= d = 10110011001100110011 f -= e = 10000000000000000000 f ^= c = 00101010101010101010 f += b = 001010101010101010101000000001 f <<=5 = 00000001010101010101010101000000001 f >>=10= 0101010101010101000000001 l = 101010101010101010100011001100110011001110101010101010101010 BitPattern pat = 0011XXXX0011XXXX0011 pat.pattern = 00110011001100110011 pat.mask = 11110000111100001111 l.index(pat) = 20 l.index(pat,-1)= 20 l.before(pat) = 10101010101010101010 l.at(pat) = 00110011001100110011 l.after(pat) = 10101010101010101010 b.set(0) :1000000001 b.set(65): 100000000100000000000000000000000000000000000000000000000000000001 b.clear(2): 100000000100000000000000000000000000000000000000000000000000000001 b.invert(11,20): 100000000100111111111000000000000000000000000000000000000000000001 b.set(21,30): 100000000100111111111111111111100000000000000000000000000000000001 b.clear(31, 40): 100000000100111111111111111111100000000000000000000000000000000001 b.set(0) :10110011001100110011 b.set(65): 101100110011001100110000000000000000000000000000000000000000000001 b.clear(2): 100100110011001100110000000000000000000000000000000000000000000001 b.invert(11,20): 100100110010110011001000000000000000000000000000000000000000000001 b.set(21,30): 100100110010110011001111111111100000000000000000000000000000000001 b.clear(31, 40): 100100110010110011001111111111100000000000000000000000000000000001 k = 0101 c.before(k) = 1 c.at(k) = 0101 c.after(k) = 010101010101010 c.after(k)=k :101010101 c.before(k)=k:010101010101 reverse(k) = 1010 k.left_trim(0) : 101 k.right_trim(1) : 10 k = 0110 c.before(k) = 0 c.at(k) = 0110 c.after(k) = 011001100110011 c.after(k)=k :001100110 c.before(k)=k:011001100110 reverse(k) = 0110 k.left_trim(0) : 110 k.right_trim(1) : 110 End of test. tRandom five random ACG integers: 1525072166 1954057046 3406008937 226879594 4107049426 five random MLCG integers: 1341853672 83475514 936613571 888739672 2097844081 Binomial r1( 100, 0.50, &gen1) ... five samples: 45 52 59 49 60 Statistics for 100 samples: samples: 100 min: 40 max: 64 mean: 50.78 stdDev: 4.42577 var: 19.5875 confidence(95): 0.87826 Erlang r2( 2.0, 0.5, &gen1) ... five samples: 1.79909 1.92988 2.50815 2.31409 1.48158 Statistics for 100 samples: samples: 100 min: .592645 max: 3.81874 mean: 1.96664 stdDev: .696406 var: .484981 confidence(95): .138196 Geometric r3(&gen1, 0.5)... five samples: 3 2 2 2 3 Statistics for 100 samples: samples: 100 min: 1 max: 7 mean: 1.9 stdDev: 1.28315 var: 1.64646 confidence(95): 0.25463 HyperGeometric r4( 10.0, 150.0, &gen1)... five samples: 15.0752 5.25802 7.82211 20.4995 7.08199 Statistics for 100 samples: samples: 100 min: .044607 max: 131.508 mean: 12.6763 stdDev: 16.7567 var: 280.786 confidence(95): 3.32523 NegativeExpntl r5( 1.0, &gen1)... five samples: 1.90665 .092197 .219318 1.79202 .566202 Statistics for 100 samples: samples: 100 min: .007946 max: 4.23124 mean: .927343 stdDev: 0.8869 var: .786592 confidence(95): .175998 Normal r6( 0.0, 1.0, &gen1)... five samples: -.174892 .148871 -.479753 0.65432 -0.92688 Statistics for 100 samples: samples: 100 min: -2.22325 max: 2.61771 mean: .141292 stdDev: .972041 var: .944864 confidence(95): .192894 LogNormal r7( 1.0, 1.0, &gen1)... five samples: 2.69747 1.05379 .293461 1.01979 1.15059 Statistics for 100 samples: samples: 100 min: .021999 max: 9.52704 mean: 1.21153 stdDev: 1.40105 var: 1.96295 confidence(95): .278028 Poisson r8( 2.0, &gen1)... five samples: 0 2 1 2 1 Statistics for 100 samples: samples: 100 min: 0 max: 5 mean: 2 stdDev: 1.31041 var: 1.71717 confidence(95): 0.26004 DiscreteUniform r9( 0.0, 1.0, &gen1)... five samples: 1 1 0 0 0 Statistics for 100 samples: samples: 100 min: 0 max: 1 mean: 0.45 stdDev: 0.5 var: 0.25 confidence(95): .099221 Uniform r10( 0.0, 1.0, &gen1)... five samples: .557314 .529968 .997197 0.25163 .947497 Statistics for 100 samples: samples: 100 min: .002053 max: .997197 mean: .518789 stdDev: .321429 var: .103317 confidence(95): .063785 Weibull r11( 0.5, 1.0, &gen1)... five samples: 10.4918 .295112 .184577 2.14799 0.10053 Statistics for 100 samples: samples: 100 min: .000236 max: 15.4934 mean: 1.96369 stdDev: 2.97642 var: 8.85906 confidence(95): .590647 SampleHistogram for 100 Normal samples < -4 : 0 < -3.2 : 0 < -2.4 : 0 < -1.6 : 7 < -0.8 : 15 < -2.22045e-16 : 36 < 0.8 : 15 < 1.6 : 19 < 2.4 : 7 < 3.2 : 1 < 4 : 0 < max : 0 End of test tFix Fix: identities should be displayed [X] displays the precision of a given value [*] indicates that the full precision is not used for coding reasons 0 [16] = 0.00000 [16] .5 [16] = 0.50000 [16] -.5 [17] = -0.50000 [17] .1 [33] = 0.10000 [33] -.5 [17] = -0.50000 [17] .3 [16] = 0.29999 [16] .5 [16] = 0.50000 [16] .1 [16] = 0.09998 [16] .1 [33*] = 0.09998 [33] -.2 [17] = -0.20001 [17] -.5 [17] = -0.50000 [17] .1 [16] == .1 [33*] = 1 .1 [16] == .1 [33] = 0 .1 [33] != .5 [16] = 1 .1 [33] > .5 [16] = 0 .1 [33] <= -.2 [17] = 0 1073741824 = 1.07374e+09 .5 = 0.5 .5 [17] = 0.50000 [17] -.5 [17] = -0.50000 [17] .1 [33] + .5 [16] = 0.60000 [33] .1 [33] - .5 [16] = -0.40000 [33] .1 [33] * .5 [16] = 0.05000 [49] .1 [33] * 3 = 0.30000 [33] .1 [33] * -3 = -0.30000 [33] -.1 [33] * 3 = -0.30000 [33] -.1 [33] * -3 = 0.30000 [33] .5 [17] * -2 = -1.00000 [17] .1 [33] % 25 = 0.10000 [58] .1 [33] % -25 = 0.09375 [8] .1 [33] / .5 [16] = 0.20001 [33] .1 [33] << 1 = 0.20000 [33] -.1 [33] >> 2 = 0.47500 [33] abs(-.2) = 0.20001 [17] abs(.2) = 0.20001 [17] sgn(-.2) = -1 sgn(.2) = 1 show .1 [33] len = 33 siz = 3 ref = 1 man = ccccccc8000 val = 0.1 Fix: range errors warned Fix: range error in declaration 1.1 [16] = 0.00000 [16] Fix: range error in division .5 [16] / .1 [33] = 0.00000 [16] Fix: range error in division -- division by zero .5 [16] / 0. [16] = 0.00000 [16] Fix: range error in multiply by int -- int too large .5 [17] * 32768 = -1.00000 [17] Fix: overflows saturated .95 [16] + .1 [33] = 1.00000 [33] -.1 [33] - .95 [16] = -1.00000 [33] .5 [17] * 2 = 0.99998 [17] Fix: overflows generate warnings Fix: overflow warning .95 [16] + .1 [33] = -0.94999 [33] Fix: overflow warning -.1 [33] - .95 [16] = 0.94999 [33] Fix: overflow warning .5 [17] * 2 = -0.49994 [17] tFix16 Fix16: identities should be displayed 0 = 0 .5 = 0.5 -.5 = -0.5 .1 = .100006 .5 = 0.5 .5 = 0.5 .25 = 0.25 8192 = 8192 .25 = 0.25 .25 = 0.25 .25 = 0.25 -.25 = -0.25 .1 + .5 = .600006 .1 - .5 = -.399994 .1 * .5 = .050003 .1 * 3 = .300018 .1 * -3 = -.300018 .1 / .5 = .200012 .1 << 1 = .200012 -.5 >> 2 = -0.125 .1 == .5 = 0 .1 != .5 = 1 .1 > .5 = 0 .5 <= -.5 = 0 Fix16: range errors ignored and overflows saturated 1.1 = .999969 .7 + .5 = .999969 -.5 - .7 = -1 .5 / .1 = .999969 Fix32: identities should be displayed 0 = 0 .5 = 0.5 -.5 = -0.5 .1 = 0.1 .5 = 0.5 .5 = 0.5 .25 = 0.25 536870912 = 536870912 .25 = 0.25 .25 = 0.25 .25 = 0.25 -.25 = -0.25 .1 + .5 = 0.6 .1 - .5 = -0.4 .1 * .5 = 0.05 .1 * 3 = 0.3 .1 * -3 = -0.3 .1 / .5 = 0.2 .1 << 1 = 0.2 -.5 >> 2 = -0.125 .1 == .5 = 0 .1 != .5 = 1 .1 > .5 = 0 .5 <= -.5 = 0 Fix32: range errors reported and overflows reported warning: Fix32 result out of range 1.1 = 1 warning: Fix32 result out of range .7 + .5 = -0.8 warning: Fix32 result out of range -.5 - .7 = 0.8 warning: Fix32 result out of range .5 / .1 = 1 tFix24 Fix24: identities should be displayed 0 = 0 .5 = 0.5 -.5 = -0.5 .1 = 0.1 .5 = 0.5 .5 = 0.5 .25 = 0.25 536870912 = 536870912 .25 = 0.25 .25 = 0.25 .25 = 0.25 -.25 = -0.25 .1 + .5 = 0.6 .1 - .5 = -0.4 .1 * .5 = 0.05 .1 * 3 = 0.3 .1 * -3 = -0.3 .1 / .5 = 0.2 .1 << 1 = 0.2 -.5 >> 2 = -0.125 .1 == .5 = 0 .1 != .5 = 1 .1 > .5 = 0 .5 <= -.5 = 0 Fix24: range errors ignored and overflows saturated 1.1 = 1 .7 + .5 = 1 -.5 - .7 = -1 .5 / .1 = 1 Fix48: identities should be displayed 0 = 0 .5 = 0.5 -.5 = -0.5 .1 = 0.1 .5 = 0.5 .5 = 0.5 .25 = 0.25 536870912 = 536870912 0 = 0 .25 = 0.25 .25 = 0.25 .25 = 0.25 -.25 = -0.25 .1 + .5 = 0.6 .1 - .5 = -0.4 .1 * 3 = 0.3 .1 * -3 = -0.3 .1 << 1 = 0.2 -.5 >> 2 = -0.125 .1 == .5 = 0 .1 != .5 = 1 .1 > .5 = 0 .5 <= -.5 = 0 Fix48: range errors reported and overflows reported warning: Fix48 result out of range 1.1 = 1 warning: Fix48 result out of range .7 + .5 = -0.8 warning: Fix48 result out of range -.5 - .7 = 0.8 Must run tCurses from tty tGetOpt ./tGetOpt: unrecognized option `-h' ./tGetOpt: unrecognized option `-i' option a option b option c with value `-de10' option 2 option 0 option 0 option 0 digits occur in two different argv-elements. option 3 tList intList a = sequence(1, 20); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 intList b = randseq(20); 22 14 21 22 31 29 36 49 9 34 19 10 44 41 19 45 7 28 12 32 intList c = concat(a, b); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 14 21 22 31 29 36 49 9 34 19 10 44 41 19 45 7 28 12 32 intList d = map(inc, a); 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 intList e = reverse(a); 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 intList f = select(is_odd, a); 1 3 5 7 9 11 13 15 17 19 int red = a.reduce(plus, 0); 210 int second = a[2]; 3 intList g = combine(plus, a, b); 23 16 24 26 36 35 43 57 18 44 30 22 57 55 34 61 24 46 31 52 g.del(is_odd); 16 24 26 36 18 44 30 22 34 24 46 52 b.sort(int_compare); 7 9 10 12 14 19 19 21 22 22 28 29 31 32 34 36 41 44 45 49 intList h = merge(a, b, int_compare); 1 2 3 4 5 6 7 7 8 9 9 10 10 11 12 12 13 14 14 15 16 17 18 19 19 19 20 21 22 22 28 29 31 32 34 36 41 44 45 49 h via Pix: 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 17, 18, 19, 19, 19, 20, 21, 22, 22, 28, 29, 31, 32, 34, 36, 41, 44, 45, 49, done tPlex FPtest q:[-25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 ] XPtest p:[-25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 ] MPtest p:[-25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 ] RPtest p:[-25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 ] end of tests tLList prepending... a: 9 8 7 6 5 4 3 2 1 0 appending... a: 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 b = a: 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 remove_front of first 10 elements: b: 0 1 2 3 4 5 6 7 8 9 inserting 100 after sixth element... b: 0 1 2 3 4 5 100 6 7 8 9 after a.join(b) 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 100 6 7 8 9 b: b: 999 bb: 999 prepending... a: 9 8 7 6 5 4 3 2 1 0 appending... a: 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 b = a: 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 remove_front of first 10 elements: b: 0 1 2 3 4 5 6 7 8 9 inserting 100 after sixth element... b: 0 1 2 3 4 5 100 6 7 8 9 after aa = a; aa.join(b) 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 100 6 7 8 9 b: b: 999 bb: 999 z = a: 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 remove_rear of last 10 elements: z: 9 8 7 6 5 4 3 2 1 0 inserting 100 before alternate elements... z: 100 9 100 8 100 7 100 6 100 5 100 4 100 3 100 2 100 1 100 0 inserting 200 after sixth element... z: 100 9 100 8 100 7 200 100 6 100 5 100 4 100 3 100 2 100 1 100 0 deleting alternate elements of z...100 100 100 200 6 5 4 3 2 1 0 z: 9 8 7 100 100 100 100 100 100 100 z in reverse order: 100 100 100 100 100 100 100 7 8 9 End of test tVec a: 72 14 71 72 81 29 86 49 59 84 69 10 94 41 69 95 57 78 62 82 a.sort():10 14 29 41 49 57 59 62 69 69 71 72 72 78 81 82 84 86 94 95 b = map(inc, a): 11 15 30 42 50 58 60 63 70 70 72 73 73 79 82 83 85 87 95 96 c = merge(a, b): 10 11 14 15 29 30 41 42 49 50 57 58 59 60 62 63 69 69 70 70 71 72 72 72 73 73 78 79 81 82 82 83 84 85 86 87 94 95 95 96 d = concat(a, b): 10 14 29 41 49 57 59 62 69 69 71 72 72 78 81 82 84 86 94 95 11 15 30 42 50 58 60 63 70 70 72 73 73 79 82 83 85 87 95 96 d.resize(10): 10 14 29 41 49 57 59 62 69 69 d.reverse(): 69 69 62 59 57 49 41 29 14 10 d.fill(0, 4, 4): 69 69 62 59 0 0 0 0 14 10 d.reduce(plus, 0) = 283 e = d.at(2, 5): 62 59 0 0 0 x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 y: 93 96 14 74 87 41 65 6 38 17 63 37 73 46 34 50 38 55 15 76 x + y: 93 97 16 77 91 46 71 13 46 26 73 48 85 59 48 65 54 72 33 95 x - y: -93 -95 -12 -71 -83 -36 -59 1 -30 -8 -53 -26 -61 -33 -20 -35 -22 -38 3 -57 product(x, y): 0 96 28 222 348 205 390 42 304 153 630 407 876 598 476 750 608 935 270 1444 quotient(x, y): 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 x * y: 8782 x + 2: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 x - 2: -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 x * 2: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 x / 2: 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 z(20, 1): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 z = -z: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z += x: -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 z -= x: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 x.sum(): 190 x.sumsq(): 2470 x.min(): 0 x.max(): 19 x.min_index(): 0 x.max_index(): 19 End of test tStack XP stacks: s1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] V stacks: s1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] SL stacks: s1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] End of test tQueue XP queues: q1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] V queues: q1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] SL queues: q1:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] End of test tDeque XP deques: d1:[99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 ...] DL deques: d1:[99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 ...] End of test tPQ Splaytest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] d: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] PHtest a: [2 99 76 81 41 35 14 19 95 74 7 38 91 59 87 6 96 93 51 53 ...] b: [129 5 191 71 147 17 139 193 1 47 199 33 121 103 37 167 145 67 51 43 ...] c: [47 27 20 28 31 15 50 46 39 29 1 1 4 43 11 8 2 7 9 26 ...] d: [2 99 76 81 41 35 14 19 95 74 7 38 91 59 87 6 96 93 51 53 ...] XPtest a: [1 3 2 7 4 5 18 29 12 6 10 8 17 21 26 34 36 15 16 19 ...] b: [1 5 3 7 13 15 9 41 27 21 23 19 35 29 11 85 51 65 49 47 ...] c: [1 2 1 3 5 2 8 4 5 6 14 3 9 11 10 7 15 12 6 28 ...] d: [1 1 2 3 3 2 6 9 5 6 4 5 7 18 8 29 15 7 16 19 ...] tSet VHtest a: [36 20 89 13 64 3 26 91 16 39 62 29 85 87 42 65 98 19 78 37 ...] b: [53 167 185 13 123 3 135 193 69 39 181 85 151 183 131 173 101 19 197 87 ...] c: [36 49 46 3 26 16 39 29 12 42 19 32 9 1 22 35 48 25 2 15 ...] d: [89 13 93 3 55 39 29 85 21 65 19 23 91 9 71 81 41 35 63 17 ...] VOHtest a: [7 14 21 28 35 42 49 56 63 70 77 84 91 98 5 12 19 26 33 40 ...] b: [7 163 21 133 35 49 63 129 77 159 91 181 105 137 119 5 185 19 197 33 ...] c: [7 14 21 28 35 42 49 5 12 19 26 33 40 47 3 10 17 24 31 38 ...] d: [7 21 35 49 63 77 91 5 19 33 47 61 75 89 3 17 31 45 59 73 ...] CHtest a: [72 36 85 49 13 3 98 62 26 16 75 39 29 88 52 42 6 65 55 19 ...] b: [167 49 85 121 13 3 157 193 111 39 75 147 29 183 137 65 101 173 55 19 ...] c: [36 13 49 3 26 16 39 29 6 42 19 32 45 9 22 35 12 48 25 38 ...] d: [13 49 85 3 39 75 29 65 19 55 91 9 45 81 35 71 25 61 97 15 ...] SLtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [3 197 151 161 81 69 27 37 189 147 13 75 181 117 173 11 191 185 101 105 ...] c: [33 2 48 18 37 5 35 49 1 12 50 9 31 26 10 42 17 13 11 21 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] XPtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [3 197 151 161 81 69 27 37 189 147 13 75 181 117 173 11 191 185 101 105 ...] c: [33 2 48 18 37 5 35 49 1 12 50 9 31 26 10 42 17 13 11 21 ...] d: [51 13 53 27 55 7 57 29 59 15 61 31 63 1 65 33 67 17 69 35 ...] OXPtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] OSLtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] BSTtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] AVLtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] Splaytest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] d: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] tBag VHtest a: [36 20 89 13 64 3 26 91 16 39 62 29 85 87 42 65 98 19 78 37 ...] b: [53 167 185 13 123 3 135 193 69 39 181 85 151 183 131 173 101 19 197 87 ...] c: [36 37 14 49 46 3 26 3 16 39 19 29 42 12 42 35 39 19 28 5 ...] d: [72 46 77 13 31 3 26 62 16 39 11 29 52 42 42 65 78 55 78 93 ...] CHtest a: [72 36 85 49 13 3 98 62 26 16 75 39 29 88 52 42 6 65 55 19 ...] b: [167 49 85 121 13 3 157 193 111 39 75 147 29 183 137 65 101 173 55 19 ...] c: [36 36 49 13 13 49 3 3 26 26 16 16 39 39 29 29 6 42 6 42 ...] d: [72 36 36 72 85 49 13 13 49 85 3 3 98 62 26 26 62 98 16 16 ...] SLtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [3 197 151 161 81 69 27 37 189 147 13 75 181 117 173 11 191 185 101 105 ...] c: [33 2 48 18 37 5 35 49 1 12 50 9 31 26 10 42 37 17 13 11 ...] d: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] XPtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [3 197 151 161 81 69 27 37 189 147 13 75 181 117 173 11 191 185 101 105 ...] c: [33 2 48 18 37 5 35 49 1 12 50 9 31 26 10 42 37 17 13 11 ...] d: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] Splaytest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] d: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] OSLtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] d: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] OXPtest a: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...] b: [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 ...] c: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] d: [1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 ...] tMap Splaytest a: [(1, 65) (2, 3) (3, 96) (4, 36) (5, 74) (6, 9) (7, 70) (8, 97) (9, 1) (10, 24) (11, 100) (12, 17) (13, 61) (14, 52) (15, 19) (16, 84) (17, 73) (18, 34) (19, 26) (20, 22) ...] b: [(1, 9) (2, 31) (3, 2) (4, 32) (5, 62) (6, 30) (7, 87) (8, 98) (9, 6) (10, 49) (11, 44) (12, 47) (13, 50) (14, 76) (15, 56) (16, 57) (17, 12) (18, 54) (19, 15) (20, 83) ...] c: [(1, 189) (2, 195) (3, 197) (4, 57) (5, 125) (6, 135) (7, 149) (8, 129) (9, 69) (10, 9) (11, 163) (12, 59) (13, 171) (14, 137) (15, 141) (16, 35) (17, 75) (18, 49) (19, 173) (20, 93) ...] d: [(1, 1) (2, 2) (3, 3) (4, 4) (5, 5) (6, 6) (7, 7) (8, 8) (9, 9) (10, 10) (11, 11) (12, 12) (13, 13) (14, 14) (15, 15) (16, 16) (17, 17) (18, 18) (19, 19) (20, 20) ...] VHtest a: [(36, 25) (20, 22) (89, 56) (13, 61) (64, 49) (3, 96) (26, 63) (91, 55) (16, 84) (39, 54) (62, 5) (29, 50) (85, 92) (87, 7) (42, 94) (65, 47) (98, 8) (19, 26) (78, 91) (37, 33) ...] b: [(36, 4) (20, 83) (34, 18) (85, 38) (68, 84) (3, 2) (26, 19) (14, 76) (16, 57) (39, 23) (62, 90) (29, 53) (52, 14) (46, 34) (42, 21) (65, 1) (37, 73) (19, 15) (78, 95) (80, 86) ...] c: [(36, 161) (20, 93) (34, 185) (85, 45) (68, 7) (3, 197) (26, 101) (14, 137) (16, 35) (39, 77) (62, 177) (29, 83) (52, 117) (46, 143) (42, 121) (65, 3) (37, 157) (19, 173) (78, 97) (80, 139) ...] d: [(72, 72) (77, 77) (13, 13) (3, 3) (26, 26) (16, 16) (39, 39) (29, 29) (52, 52) (42, 42) (65, 65) (55, 55) (78, 78) (91, 91) (9, 9) (22, 22) (35, 35) (48, 48) (61, 61) (74, 74) ...] CHtest a: [(72, 66) (36, 25) (85, 92) (49, 10) (13, 61) (3, 96) (98, 8) (62, 5) (26, 63) (16, 84) (75, 51) (39, 54) (29, 50) (88, 81) (52, 32) (42, 94) (6, 9) (65, 47) (55, 45) (19, 26) ...] b: [(72, 41) (36, 4) (49, 64) (13, 50) (85, 38) (3, 2) (62, 90) (98, 82) (26, 19) (16, 57) (75, 80) (39, 23) (29, 53) (88, 100) (52, 14) (6, 30) (42, 21) (65, 1) (55, 91) (19, 15) ...] c: [(72, 53) (36, 161) (49, 67) (13, 171) (85, 45) (3, 197) (62, 177) (98, 95) (26, 101) (16, 35) (75, 25) (39, 77) (29, 83) (88, 47) (52, 117) (6, 135) (42, 121) (65, 3) (55, 89) (19, 173) ...] d: [(36, 36) (72, 72) (13, 13) (49, 49) (85, 85) (3, 3) (26, 26) (62, 62) (98, 98) (16, 16) (39, 39) (75, 75) (29, 29) (52, 52) (88, 88) (6, 6) (42, 42) (65, 65) (19, 19) (55, 55) ...] AVLtest a: [(1, 65) (2, 3) (3, 96) (4, 36) (5, 74) (6, 9) (7, 70) (8, 97) (9, 1) (10, 24) (11, 100) (12, 17) (13, 61) (14, 52) (15, 19) (16, 84) (17, 73) (18, 34) (19, 26) (20, 22) ...] b: [(1, 9) (2, 31) (3, 2) (4, 32) (5, 62) (6, 30) (7, 87) (8, 98) (9, 6) (10, 49) (11, 44) (12, 47) (13, 50) (14, 76) (15, 56) (16, 57) (17, 12) (18, 54) (19, 15) (20, 83) ...] c: [(1, 189) (2, 195) (3, 197) (4, 57) (5, 125) (6, 135) (7, 149) (8, 129) (9, 69) (10, 9) (11, 163) (12, 59) (13, 171) (14, 137) (15, 141) (16, 35) (17, 75) (18, 49) (19, 173) (20, 93) ...] d: [(1, 1) (2, 2) (3, 3) (4, 4) (5, 5) (6, 6) (7, 7) (8, 8) (9, 9) (10, 10) (11, 11) (12, 12) (13, 13) (14, 14) (15, 15) (16, 16) (17, 17) (18, 18) (19, 19) (20, 20) ...] RAVLtest a: [(1, 65) (2, 3) (3, 96) (4, 36) (5, 74) (6, 9) (7, 70) (8, 97) (9, 1) (10, 24) (11, 100) (12, 17) (13, 61) (14, 52) (15, 19) (16, 84) (17, 73) (18, 34) (19, 26) (20, 22) ...] b: [(1, 9) (2, 31) (3, 2) (4, 32) (5, 62) (6, 30) (7, 87) (8, 98) (9, 6) (10, 49) (11, 44) (12, 47) (13, 50) (14, 76) (15, 56) (16, 57) (17, 12) (18, 54) (19, 15) (20, 83) ...] c: [(1, 189) (2, 195) (3, 197) (4, 57) (5, 125) (6, 135) (7, 149) (8, 129) (9, 69) (10, 9) (11, 163) (12, 59) (13, 171) (14, 137) (15, 141) (16, 35) (17, 75) (18, 49) (19, 173) (20, 93) ...] d: [(1, 1) (2, 2) (3, 3) (4, 4) (5, 5) (6, 6) (7, 7) (8, 8) (9, 9) (10, 10) (11, 11) (12, 12) (13, 13) (14, 14) (15, 15) (16, 16) (17, 17) (18, 18) (19, 19) (20, 20) ...] 4, 32) (5, 62) (6, 30) (7, 87) (8, 98) (9, 6) (10, 49) (11, 44) (12, 47) (13, 50) (14, 76) (15, 56) (16, 57) (17, 12) (18, 54) (19, 15) (20, 83) ...] c: [(1, 189) (2, 195) (3, 197) (4, 57) (5, 125) (6, 135) (7, 149) (8, 129) (9, 69) (10, 9) (11, 163) (12, 59) (13, 171) (14, 137) (15, 141) (libg++/tests/tBitSet.inp 644 473 0 0 4677700042 10272 libg++/tests/tBitString.inp 644 473 0 0 4677700042 11005 libg++/tests/tRandom.inp 644 473 0 0 4677700042 10320 libg++/tests/tList.inp 644 473 0 0 4677700042 10013 libg++/tests/tLList.inp 644 473 0 0 4677700042 10127 libg++/tests/tVec.inp 644 473 0 0 4677700042 7615 libg++/tests/tMap.inp 644 473 0 0 4677700043 7616 libg++/tests/tStack.inp 644 473 0 0 4677700043 10146 libg++/tests/tCurses.inp 644 473 0 6 4677700043 10353 123 a ) (17, 75) (18, 49) (19, 173) (20, 93) ...] d: [(1, 1) (2, 2) (3, 3) (4, 4) (5, 5) (6, 6) (7, 7) (8, 8) (9, 9) (10, 10) (11, 11) (12, 12) (13, 13) (14, 14) (15, 15) (16, 16) (17, 17) (18, 18) (19, 19) (20, 20) ...] 4, 32) (5, 62) (6, 30) (7, 87) (8, 98) (9, 6) (10, 49) (11, 44) (12, 47) (13, 50) (14, 76) (15, 56) (16, 57) (17, 12) (18, 54) (19, 15) (20, 83) ...] c: [(1, 189) (2, 195) (3, 197) (4, 57) (5, 125) (6, 135) (7, 149) (8, 129) (9, 69) (10, 9) (11, 163) (12, 59) (13, 171) (14, 137) (15, 141) (libg++/tests/tQueue.inp 644 473 0 0 4677700043 10165 libg++/tests/tFix.inp 644 473 0 0 4677700043 7627 libg++/tests/tFix16.inp 644 473 0 0 4677700043 7776 libg++/tests/tFix24.inp 644 473 0 0 4677700043 7775 libg++/tests/tDeque.inp 644 473 0 0 4677700043 10144 libg++/tests/ERR 644 473 0 43523 4700633544 6677 echo "/^PROTODIR=/c\\" > sedscript echo "PROTODIR=../g++-include" >> sedscript sed < ../genclass.sh > ./genclass -f sedscript chmod 0755 genclass rm -f sedscript g++ -c -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe test.bye.cc -o test.bye g++ -c -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe test.bye2.cc -o test.bye2 g++ -c -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe test.shell.cc -o test.shell g++ test.hello.o -lm -o test0 ld: cannot find "test.hello.o" *** Error code 1 g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tFile.cc g++ tFile.o -o tFile -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tObstack.cc g++ tObstack.o -o tObstack -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tString.cc g++ tString.o -o tString -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tInteger.cc g++ tInteger.o -o tInteger -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c twrapper.cc twrapper.cc: In method class Integer MemoizedInteger::()MemoizedInteger (int, auto class Integer (class MemoizedInteger ::*)(class Integer ,class Integer ), class Integer, class Integer): twrapper.cc:234: warning: cannot pass objects of type `Integer' through `...' g++ twrapper.o -o twrapper -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tgwrapper.cc tgwrapper.cc: In method MemoizedIntegerElem::MemoizedIntegerElem (int, auto class Integer (class MemoizedInteger ::*)(...), class Integer, ...): tgwrapper.cc:220: warning: varargs function cannot be inline g++ tgwrapper.o -o tgwrapper -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tRational.cc g++ tRational.o -o tRational -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tComplex.cc g++ tComplex.o -o tComplex -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tBitSet.cc g++ tBitSet.o -o tBitSet -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tBitString.cc g++ tBitString.o -o tBitString -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tRandom.cc g++ tRandom.o -o tRandom -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tFix.cc g++ tFix.o -o tFix -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tFix16.cc g++ tFix16.o -o tFix16 -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tFix24.cc g++ tFix24.o -o tFix24 -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tCurses.cc g++ tCurses.o -o tCurses -lg++ -lcurses -ltermcap -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tGetOpt.cc g++ tGetOpt.o -o tGetOpt -lm ./genclass int val defs i genclass warning: class has a .h but no .cc file ./genclass int val XPStack i genclass warning: class has a .h but no .cc file ./genclass int val SLStack i genclass warning: class has a .h but no .cc file ./genclass int val XPQueue i genclass warning: class has a .h but no .cc file ./genclass int val SLQueue i genclass warning: class has a .h but no .cc file ./genclass int val XPDeque i genclass warning: class has a .h but no .cc file ./genclass int val DLDeque i genclass warning: class has a .h but no .cc file ./genclass int val Stack i genclass warning: class has a .h but no .cc file ./genclass int val Queue i genclass warning: class has a .h but no .cc file ./genclass int val Deque i genclass warning: class has a .h but no .cc file ./genclass int val List i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iList.cc ./genclass int val SLList i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSLList.cc ./genclass int val DLList i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iDLList.cc ./genclass int val Vec i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVec.cc ./genclass int val AVec i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iAVec.cc ./genclass int val Plex i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iPlex.cc iPlex.cc: In method void intIChunk::error (const char *)const : iPlex.cc:33: warning: `volatile' function does return iPlex.cc: In method void intPlex::error (const char *)const : iPlex.cc:110: warning: `volatile' function does return ./genclass int val FPlex i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iFPlex.cc ./genclass int val XPlex i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iXPlex.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPlex.cc:25: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val RPlex i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iRPlex.cc iRPlex.h: In method void intRPlex::set_cache (const class intIChunk *)const : In file included from iRPlex.cc:25: iRPlex.h:171: warning: assignment of non-const * pointer from const * ./genclass int val MPlex i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iMPlex.cc iMPlex.h: In method void intMPlex::set_cache (const class intMChunk *)const : In file included from iMPlex.cc:25: iMPlex.h:318: warning: assignment of non-const * pointer from const * ./genclass int val Set i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSet.cc ./genclass int val Bag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iBag.cc ./genclass -2 int val int val Map i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iMap.cc ./genclass int val PQ i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iPQ.cc ./genclass int val XPSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iXPSet.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPSet.h:30, from iXPSet.cc:24: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val OXPSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iOXPSet.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iOXPSet.h:30, from iOXPSet.cc:24: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val SLSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSLSet.cc ./genclass int val OSLSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iOSLSet.cc ./genclass int val BSTSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iBSTSet.cc ./genclass int val AVLSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iAVLSet.cc ./genclass int val SplaySet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSplaySet.cc ./genclass int val VHSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVHSet.cc ./genclass int val VOHSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVOHSet.cc ./genclass int val CHSet i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iCHSet.cc ./genclass int val XPBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iXPBag.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPBag.h:30, from iXPBag.cc:24: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val OXPBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iOXPBag.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iOXPBag.h:6, from iOXPBag.cc:24: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val SLBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSLBag.cc ./genclass int val OSLBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iOSLBag.cc ./genclass int val SplayBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSplayBag.cc ./genclass int val VHBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVHBag.cc ./genclass int val CHBag i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iCHBag.cc ./genclass -2 int val int val VHMap i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVHMap.cc ./genclass -2 int val int val CHMap i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iCHMap.cc ./genclass -2 int val int val SplayMap i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSplayMap.cc ./genclass -2 int val int val AVLMap i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iAVLMap.cc ./genclass -2 int val int val RAVLMap i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iRAVLMap.cc ./genclass int val SplayPQ i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iSplayPQ.cc ./genclass int val PHPQ i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iPHPQ.cc ./genclass int val XPPQ i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iXPPQ.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPPQ.h:30, from iXPPQ.cc:24: iXPlex.h:238: warning: assignment of non-const * pointer from const * ./genclass int val VStack i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVStack.cc ./genclass int val VQueue i g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c iVQueue.cc rm -f libtest.a ar r libtest.a iList.o iSLList.o iDLList.o iVec.o iAVec.o iPlex.o iFPlex.o iXPlex.o iRPlex.o iMPlex.o iSet.o iBag.o iMap.o iPQ.o iXPSet.o iOXPSet.o iSLSet.o iOSLSet.o iBSTSet.o iAVLSet.o iSplaySet.o iVHSet.o iVOHSet.o iCHSet.o iXPBag.o iOXPBag.o iSLBag.o iOSLBag.o iSplayBag.o iVHBag.o iCHBag.o iVHMap.o iCHMap.o iSplayMap.o iAVLMap.o iRAVLMap.o iSplayPQ.o iPHPQ.o iXPPQ.o iVStack.o iVQueue.o ar: creating libtest.a gnuranlib libtest.a g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tList.cc g++ tList.o -o tList libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tPlex.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from tPlex.cc:183: iXPlex.h:238: warning: assignment of non-const * pointer from const * iMPlex.h: In method void intMPlex::set_cache (const class intMChunk *)const : In file included from tPlex.cc:352: iMPlex.h:318: warning: assignment of non-const * pointer from const * iRPlex.h: In method void intRPlex::set_cache (const class intIChunk *)const : In file included from tPlex.cc:537: iRPlex.h:171: warning: assignment of non-const * pointer from const * g++ tPlex.o -o tPlex libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tLList.cc g++ tLList.o -o tLList libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tVec.cc g++ tVec.o -o tVec libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tStack.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPStack.h:31, from tStack.cc:38: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tStack.o -o tStack libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tQueue.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPQueue.h:31, from tQueue.cc:38: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tQueue.o -o tQueue libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tDeque.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPDeque.h:31, from tDeque.cc:39: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tDeque.o -o tDeque libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tPQ.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPPQ.h:31, from tPQ.cc:75: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tPQ.o -o tPQ libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tSet.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPSet.h:31, from tSet.cc:108: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tSet.o -o tSet libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tBag.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : In file included from iXPBag.h:31, from tBag.cc:101: iXPlex.h:238: warning: assignment of non-const * pointer from const * g++ tBag.o -o tBag libtest.a -lm g++ -DUSG -I../g++-include -g -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tMap.cc g++ tMap.o -o tMap libtest.a -lm -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -pipe -c tBag.cc iXPlex.h: In method void intXPlex::set_cache (const class intIChunk *)const : Ilibg++/src/ACG.cc 644 473 0 20417 4677700044 6652 #include "ACG.h" #include "assert.h" // // This is an extension of the older implementation of Algorithm M // which I previously supplied. The main difference between this // version and the old code are: // // + Andres searched high & low for good constants for // the LCG. // // + theres more bit chopping going on. // // The following contains his comments. // // agn@UNH.CS.CMU.EDU sez.. // // The generator below is based on 2 well known // methods: Linear Congruential (LCGs) and Additive // Congruential generators (ACGs). // // The LCG produces the longest possible sequence // of 32 bit random numbers, each being unique in // that sequence (it has only 32 bits of state). // It suffers from 2 problems: a) Independence // isnt great, that is the (n+1)th number is // somewhat related to the preceding one, unlike // flipping a coin where knowing the past outcomes // dont help to predict the next result. b) // Taking parts of a LCG generated number can be // quite non-random: for example, looking at only // the least significant byte gives a permuted // 8-bit counter (that has a period length of only // 256). The advantage of an LCA is that it is // perfectly uniform when run for the entire period // length (and very uniform for smaller sequences // too, if the parameters are chosen carefully). // // ACGs have extremly long period lengths and // provide good independence. Unfortunately, // uniformity isnt not too great. Furthermore, I // didnt find any theoretically analysis of ACGs // that addresses uniformity. // // The RNG given below will return numbers // generated by an LCA that are permuted under // control of a ACG. 2 permutations take place: the // 4 bytes of one LCG generated number are // subjected to one of 16 permutations selected by // 4 bits of the ACG. The permutation a such that // byte of the result may come from each byte of // the LCG number. This effectively destroys the // structure within a word. Finally, the sequence // of such numbers is permuted within a range of // 256 numbers. This greatly improves independence. // // // Algorithm M as describes in Knuths "Art of Computer Programming", // Vol 2. 1969 // is used with a linear congruential generator (to get a good uniform // distribution) that is permuted with a Fibonacci additive congruential // generator to get good independence. // // Bit, byte, and word distributions were extensively tested and pass // Chi-squared test near perfect scores (>7E8 numbers tested, Uniformity // assumption holds with probability > 0.999) // // Run-up tests for on 7E8 numbers confirm independence with // probability > 0.97. // // Plotting random points in 2d reveals no apparent structure. // // Autocorrelation on sequences of 5E5 numbers (A(i) = SUM X(n)*X(n-i), // i=1..512) // results in no obvious structure (A(i) ~ const). // // Except for speed and memory requirements, this generator outperforms // random() for all tests. (random() scored rather low on uniformity tests, // while independence test differences were less dramatic). // // AGN would like to.. // thanks to M.Mauldin, H.Walker, J.Saxe and M.Molloy for inspiration & help. // // And I would (DGC) would like to thank Donald Kunth for AGN for letting me // use his extensions in this implementation. // // // Part of the table on page 28 of Knuth, vol II. This allows us // to adjust the size of the table at the expense of shorter sequences. // static randomStateTable[][3] = { {3,7,16}, {4,9, 32}, {3,10, 32}, {1,11, 32}, {1,15,64}, {3,17,128}, {7,18,128}, {3,20,128}, {2,21, 128}, {1,22, 128}, {5,23, 128}, {3,25, 128}, {2,29, 128}, {3,31, 128}, {13,33, 256}, {2,35, 256}, {11,36, 256}, {14,39,256}, {3,41,256}, {9,49,256}, {3,52,256}, {24,55,256}, {7,57, 256}, {19,58,256}, {38,89,512}, {17,95,512}, {6,97,512}, {11,98,512}, {-1,-1,-1} }; // // spatial permutation table // RANDOM_PERM_SIZE must be a power of two // #define RANDOM_PERM_SIZE 64 unsigned long randomPermutations[RANDOM_PERM_SIZE] = { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, // 3210 0x0000ffff, 0x00ff0000, 0x00000000, 0xff000000, // 2310 0xff0000ff, 0x0000ff00, 0x00000000, 0x00ff0000, // 3120 0x00ff00ff, 0x00000000, 0xff00ff00, 0x00000000, // 1230 0xffff0000, 0x000000ff, 0x00000000, 0x0000ff00, // 3201 0x00000000, 0x00ff00ff, 0x00000000, 0xff00ff00, // 2301 0xff000000, 0x00000000, 0x000000ff, 0x00ffff00, // 3102 0x00000000, 0x00000000, 0x00000000, 0xffffffff, // 2103 0xff00ff00, 0x00000000, 0x00ff00ff, 0x00000000, // 3012 0x0000ff00, 0x00000000, 0x00ff0000, 0xff0000ff, // 2013 0x00000000, 0x00000000, 0xffffffff, 0x00000000, // 1032 0x00000000, 0x0000ff00, 0xffff0000, 0x000000ff, // 1023 0x00000000, 0xffffffff, 0x00000000, 0x00000000, // 0321 0x00ffff00, 0xff000000, 0x00000000, 0x000000ff, // 0213 0x00000000, 0xff000000, 0x0000ffff, 0x00ff0000, // 0132 0x00000000, 0xff00ff00, 0x00000000, 0x00ff00ff // 0123 }; // // SEED_TABLE_SIZE must be a power of 2 // #define SEED_TABLE_SIZE 32 static unsigned long seedTable[SEED_TABLE_SIZE] = { 0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b, 0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf, 0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706, 0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10, 0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a, 0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32, 0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f, 0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf }; // // The LCG used to scramble the ACG // // // LC-parameter selection follows recommendations in // "Handbook of Mathematical Functions" by Abramowitz & Stegun 10th, edi. // // LC_A = 251^2, ~= sqrt(2^32) = 66049 // LC_C = result of a long trial & error series = 3907864577 // static const unsigned long LC_A = 66049; static const unsigned long LC_C = 3907864577; inline unsigned long LCG(unsigned long x) { return( x * LC_A + LC_C ); } ACG::ACG(unsigned long seed, int size) { initialSeed = seed; // // Determine the size of the state table // for (register int l = 0; randomStateTable[l][0] != -1 && randomStateTable[l][1] < size; l++); if (randomStateTable[l][1] == -1) { l--; } initialTableEntry = l; stateSize = randomStateTable[ initialTableEntry ][ 1 ]; auxSize = randomStateTable[ initialTableEntry ][ 2 ]; // // Allocate the state table & the auxillary table in a single malloc // state = new unsigned long[stateSize + auxSize]; auxState = &state[stateSize]; reset(); } // // Initialize the state // void ACG::reset() { register unsigned long u; if (initialSeed > -1 && initialSeed < SEED_TABLE_SIZE) { u = seedTable[ initialSeed ]; } else { u = initialSeed ^ seedTable[ initialSeed & (SEED_TABLE_SIZE-1) ]; } j = randomStateTable[ initialTableEntry ][ 0 ] - 1; k = randomStateTable[ initialTableEntry ][ 1 ] - 1; register int i; for(i = 0; i < stateSize; i++) { state[i] = u = LCG(u); } for (i = 0; i < auxSize; i++) { auxState[i] = u = LCG(u); } k = u % stateSize; int tailBehind = (stateSize - randomStateTable[ initialTableEntry ][ 0 ]); j = k - tailBehind; if (j < 0) { j += stateSize; } lcgRecurr = u; assert(sizeof(double) == 2 * sizeof(long)); } ACG::~ACG() { if (state) delete state; state = 0; // don't delete auxState, it's really an alias for state. } // // Returns 32 bits of random information. // unsigned long ACG::asLong() { unsigned long result = state[k] + state[j]; state[k] = result; j = (j <= 0) ? (stateSize-1) : (j-1); k = (k <= 0) ? (stateSize-1) : (k-1); short int auxIndex = (result >> 24) & (auxSize - 1); register unsigned long auxACG = auxState[auxIndex]; auxState[auxIndex] = lcgRecurr = LCG(lcgRecurr); // // 3c is a magic number. We are doing four masks here, so we // do not want to run off the end of the permutation table. // This insures that we have always got four entries left. // register unsigned long *perm = & randomPermutations[result & 0x3c]; result = *(perm++) & auxACG; result |= *(perm++) & ((auxACG << 24) | ((auxACG >> 8)& 0xffffff)); result |= *(perm++) & ((auxACG << 16) | ((auxACG >> 16) & 0xffff)); result |= *(perm++) & ((auxACG << 8) | ((auxACG >> 24) & 0xff)); return(result); } so we // do not want to run off the end of the permutation table. // This insures that we have always got four entries left. // register unsigned long *perm = & randomPermutations[result & 0x3c]; result = *(perm++) libg++/src/BitSet.cc 644 473 0 41341 4677700044 7451 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* BitSet class implementation */ #include #include #include #include #include #include volatile void BitSet::error(const char* msg) const { (*lib_error_handler)("BitSet", msg); } // globals & constants BitSetRep _nilBitSetRep = { 0, 1, 0, {0} }; // nil BitSets point here #define ONES ((unsigned short)(~0L)) #define MAXBitSetRep_SIZE ((1 << (SHORTBITS - 1)) - 1) #define MINBitSetRep_SIZE 16 #ifndef MALLOC_MIN_OVERHEAD #define MALLOC_MIN_OVERHEAD 4 #endif // break things up into .s indices and positions // mask out bits from left static inline unsigned short lmask(int p) { return ONES << p; } // mask out high bits static inline unsigned short rmask(int p) { return ONES >> (BITSETBITS - 1 - p); } inline static BitSetRep* BSnew(int newlen) { unsigned int siz = sizeof(BitSetRep) + newlen * sizeof(short) + MALLOC_MIN_OVERHEAD; unsigned int allocsiz = MINBitSetRep_SIZE;; while (allocsiz < siz) allocsiz <<= 1; allocsiz -= MALLOC_MIN_OVERHEAD; if (allocsiz >= MAXBitSetRep_SIZE * sizeof(short)) (*lib_error_handler)("BitSet", "Requested length out of range"); BitSetRep* rep = (BitSetRep *) new char[allocsiz]; bzero(rep, allocsiz); rep->sz = (allocsiz - sizeof(BitSetRep) + sizeof(short)) / sizeof(short); return rep; } BitSetRep* BitSetalloc(BitSetRep* old, const unsigned short* src, int srclen, int newvirt, int newlen) { if (old == &_nilBitSetRep) old = 0; BitSetRep* rep; if (old == 0 || newlen >= old->sz) rep = BSnew(newlen); else rep = old; rep->len = newlen; rep->virt = newvirt; if (srclen != 0 && src != rep->s) bcopy(src, rep->s, srclen * sizeof(short)); if (old != rep && old != 0) delete old; return rep; } BitSetRep* BitSetresize(BitSetRep* old, int newlen) { BitSetRep* rep; if (old == 0 || old == &_nilBitSetRep) { rep = BSnew(newlen); rep->virt = 0; } else if (newlen >= old->sz) { rep = BSnew(newlen); bcopy(old->s, rep->s, old->len * sizeof(short)); rep->virt = old->virt; delete old; } else rep = old; rep->len = newlen; return rep; } // same, for straight copy BitSetRep* BitSetcopy(BitSetRep* old, const BitSetRep* src) { BitSetRep* rep; if (old == &_nilBitSetRep) old = 0; if (src == 0 || src == &_nilBitSetRep) { if (old == 0) rep = BSnew(0); else rep = old; rep->len = 0; rep->virt = 0; } else if (old == src) return old; else { int newlen = src->len; if (old == 0 || newlen > old->sz) { rep = BSnew(newlen); if (old != 0) delete old; } else rep = old; bcopy(src->s, rep->s, newlen * sizeof(short)); rep->len = newlen; rep->virt = src->virt; } return rep; } // remove unneeded top bits inline static void trim(BitSetRep* rep) { int l = rep->len; unsigned short* s = &(rep->s[l - 1]); if (rep->virt == 0) while (l > 0 && *s-- == 0) --l; else while (l > 0 && *s-- == ONES) --l; rep->len = l; } int operator == (const BitSet& x, const BitSet& y) { return x.rep->len == y.rep->len && x.rep->virt == y.rep->virt && bcmp((void*)x.rep->s, (void*)y.rep->s, x.rep->len * sizeof(short)) == 0; } int operator <= (const BitSet& x, const BitSet& y) { if (x.rep->virt > y.rep->virt) return 0; int xl = x.rep->len; int yl = y.rep->len; unsigned short* xs = x.rep->s; unsigned short* ys = y.rep->s; unsigned short* topx = &(xs[xl]); unsigned short* topy = &(ys[yl]); while (xs < topx && ys < topy) { unsigned short a = *xs++; unsigned short b = *ys++; if ((a | b) != b) return 0; } if (xl == yl) return x.rep->virt <= y.rep->virt; else if (xl < yl) return !x.rep->virt; else return y.rep->virt; } int operator < (const BitSet& x, const BitSet& y) { if (x.rep->virt > y.rep->virt) return 0; int xl = x.rep->len; int yl = y.rep->len; unsigned short* xs = x.rep->s; unsigned short* ys = y.rep->s; unsigned short* topx = &(xs[xl]); unsigned short* topy = &(ys[yl]); int one_diff = 0; while (xs < topx && ys < topy) { unsigned short a = *xs++; unsigned short b = *ys++; unsigned short c = a | b; if (c != b) return 0; else if (c != a) one_diff = 1; } if (xl == yl) return x.rep->virt < y.rep->virt || (one_diff && x.rep->virt == y.rep->virt); else if (xl < yl) return !x.rep->virt; else return y.rep->virt; } BitSet shorttoBitSet(unsigned short w) return r { r.rep = BitSetalloc(0, &w, 1, 0, 2); trim(r.rep); } BitSet longtoBitSet(unsigned long w) return r; { unsigned short u[2]; u[0] = w & ((unsigned short)(~(0))); u[1] = w >> BITSETBITS; r.rep = BitSetalloc(0, &u[0], 2, 0, 3); trim(r.rep); } int BitSet::empty() const { if (rep->virt == 1) return 0; unsigned short* bots = rep->s; unsigned short* s = &(bots[rep->len - 1]); while (s >= bots) if (*s-- != 0) return 0; return 1; } int BitSet::count(int b) const { if (b == rep->virt) return -1; int l = 0; unsigned short* s = rep->s; unsigned short* tops = &(s[rep->len]); if (b == 1) { while (s < tops) { unsigned short a = *s++; for (int i = 0; i < BITSETBITS && a != 0; ++i) { if (a & 1) ++l; a >>= 1; } } } else { unsigned short maxbit = 1 << (BITSETBITS - 1); while (s < tops) { unsigned short a = *s++; for (int i = 0; i < BITSETBITS; ++i) { if ((a & maxbit) == 0) ++l; a <<= 1; } } } return l; } BitSetRep* BitSetcmpl(const BitSetRep* src, BitSetRep* r) { r = BitSetcopy(r, src); r->virt = !src->virt; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); if (r->len == 0) *rs = ONES; else { while (rs < topr) { unsigned short cmp = ~(*rs); *rs++ = cmp; } } trim(r); return r; } BitSetRep* BitSetop(const BitSetRep* x, const BitSetRep* y, BitSetRep* r, char op) { int xrsame = x == r; int yrsame = y == r; int xv = x->virt; int yv = y->virt; int xl = x->len; int yl = y->len; int rl = (xl >= yl)? xl : yl; r = BitSetresize(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); int av, bv; const unsigned short* as; const unsigned short* topa; const unsigned short* bs; const unsigned short* topb; if (xl <= yl) { as = (xrsame)? r->s : x->s; av = xv; topa = &(as[xl]); bs = (yrsame)? r->s : y->s; bv = yv; topb = &(bs[yl]); } else { as = (yrsame)? r->s : y->s; av = yv; topa = &(as[yl]); bs = (xrsame)? r->s : x->s; bv = xv; topb = &(bs[xl]); if (op == '-') // reverse sense of difference op = 'D'; } switch (op) { case '&': r->virt = av & bv; while (as < topa) *rs++ = *as++ & *bs++; if (av) while (rs < topr) *rs++ = *bs++; else while (rs < topr) *rs++ = 0; break; case '|': r->virt = av | bv; while (as < topa) *rs++ = *as++ | *bs++; if (av) while (rs < topr) *rs++ = ONES; else while (rs < topr) *rs++ = *bs++; break; case '^': r->virt = av ^ bv; while (as < topa) *rs++ = *as++ ^ *bs++; if (av) while (rs < topr) *rs++ = ~(*bs++); else while (rs < topr) *rs++ = *bs++; break; case '-': r->virt = av & ~(bv); while (as < topa) *rs++ = *as++ & ~(*bs++); if (av) while (rs < topr) *rs++ = ~(*bs++); else while (rs < topr) *rs++ = 0; break; case 'D': r->virt = ~(av) & (bv); while (as < topa) *rs++ = ~(*as++) & (*bs++); if (av) while (rs < topr) *rs++ = 0; else while (rs < topr) *rs++ = *bs++; break; } trim(r); return r; } void BitSet::set(int p) { if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); int pos = BitSet_pos(p); if (index >= rep->len) { if (rep->virt) return; else rep = BitSetresize(rep, index+1); } rep->s[index] |= (1 << pos); } void BitSet::clear(int p) { if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); if (index >= rep->len) { if (rep->virt == 0) return; else rep = BitSetresize(rep, index+1); } rep->s[index] &= ~(1 << BitSet_pos(p)); } void BitSet::invert(int p) { if (p < 0) error("Illegal bit index"); int index = BitSet_index(p); if (index >= rep->len) rep = BitSetresize(rep, index+1); rep->s[index] ^= (1 << BitSet_pos(p)); } void BitSet::set(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); int index1 = BitSet_index(from); int pos1 = BitSet_pos(from); if (rep->virt && index1 >= rep->len) return; int index2 = BitSet_index(to); int pos2 = BitSet_pos(to); if (index2 >= rep->len) rep = BitSetresize(rep, index2+1); unsigned short* s = &(rep->s[index1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (index2 == index1) *s |= m1 & m2; else { *s++ |= m1; unsigned short* top = &(rep->s[index2]); *top |= m2; while (s < top) *s++ = ONES; } } void BitSet::clear(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); int index1 = BitSet_index(from); int pos1 = BitSet_pos(from); if (!rep->virt && index1 >= rep->len) return; int index2 = BitSet_index(to); int pos2 = BitSet_pos(to); if (index2 >= rep->len) rep = BitSetresize(rep, index2+1); unsigned short* s = &(rep->s[index1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (index2 == index1) *s &= ~(m1 & m2); else { *s++ &= ~m1; unsigned short* top = &(rep->s[index2]); *top &= ~m2; while (s < top) *s++ = 0; } } void BitSet::invert(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); int index1 = BitSet_index(from); int pos1 = BitSet_pos(from); int index2 = BitSet_index(to); int pos2 = BitSet_pos(to); if (index2 >= rep->len) rep = BitSetresize(rep, index2+1); unsigned short* s = &(rep->s[index1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (index2 == index1) *s ^= m1 & m2; else { *s++ ^= m1; unsigned short* top = &(rep->s[index2]); *top ^= m2; while (s < top) { unsigned short cmp = ~(*s); *s++ = cmp; } } } int BitSet::test(int from, int to) const { if (from < 0 || from > to) return 0; int index1 = BitSet_index(from); int pos1 = BitSet_pos(from); if (index1 >= rep->len) return rep->virt; int index2 = BitSet_index(to); int pos2 = BitSet_pos(to); if (index2 >= rep->len) { if (rep->virt) return 1; else { index2 = rep->len - 1; pos2 = BITSETBITS - 1; } } unsigned short* s = &(rep->s[index1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (index2 == index1) return (*s & m1 & m2) != 0; else { if (*s++ & m1) return 1; unsigned short* top = &(rep->s[index2]); if (*top & m2) return 1; while (s < top) if (*s++ != 0) return 1; return 0; } } int BitSet::next(int p, int b) const { ++p; int index = BitSet_index(p); int pos = BitSet_pos(p); int l = rep->len; if (index >= l) { if (rep->virt == b) return p; else return -1; } int j = index; unsigned short* s = rep->s; unsigned short a = s[j] >> pos; int i = pos; if (b == 1) { for (; i < BITSETBITS && a != 0; ++i) { if (a & 1) return j * BITSETBITS + i; a >>= 1; } for (++j; j < l; ++j) { a = s[j]; for (i = 0; i < BITSETBITS && a != 0; ++i) { if (a & 1) return j * BITSETBITS + i; a >>= 1; } } if (rep->virt) return j * BITSETBITS; else return -1; } else { for (; i < BITSETBITS; ++i) { if ((a & 1) == 0) return j * BITSETBITS + i; a >>= 1; } for (++j; j < l; ++j) { a = s[j]; if (a != ONES) { for (i = 0; i < BITSETBITS; ++i) { if ((a & 1) == 0) return j * BITSETBITS + i; a >>= 1; } } } if (!rep->virt) return j * BITSETBITS; else return -1; } } int BitSet::previous(int p, int b) const { if (--p < 0) return -1; int index = BitSet_index(p); int pos = BitSet_pos(p); unsigned short* s = rep->s; int l = rep->len; if (index >= l) { if (rep->virt == b) return p; else { index = l - 1; pos = BITSETBITS - 1; } } int j = index; unsigned short a = s[j]; int i = pos; unsigned short maxbit = 1 << pos; if (b == 1) { for (; i >= 0 && a != 0; --i) { if (a & maxbit) return j * BITSETBITS + i; a <<= 1; } maxbit = 1 << (BITSETBITS - 1); for (--j; j >= 0; --j) { a = s[j]; for (i = BITSETBITS - 1; i >= 0 && a != 0; --i) { if (a & maxbit) return j * BITSETBITS + i; a <<= 1; } } return -1; } else { if (a != ONES) { for (; i >= 0; --i) { if ((a & maxbit) == 0) return j * BITSETBITS + i; a <<= 1; } } maxbit = 1 << (BITSETBITS - 1); for (--j; j >= 0; --j) { a = s[j]; if (a != ONES) { for (i = BITSETBITS - 1; i >= 0; --i) { if ((a & maxbit) == 0) return j * BITSETBITS + i; a <<= 1; } } } return -1; } } int BitSet::last(int b) const { if (b == rep->virt) return -1; else return previous((rep->len) * BITSETBITS, b); } extern AllocRing _libgxx_fmtq; const char* BitSettoa(const BitSet& x, char f, char t, char star) { trim(x.rep); int wrksiz = (x.rep->len + 1) * BITSETBITS + 2; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* fmt = fmtbase; const unsigned short* s = x.rep->s; const unsigned short* top = &(s[x.rep->len - 1]); while (s < top) { unsigned short a = *s++; for (int j = 0; j < BITSETBITS; ++j) { *fmt++ = (a & 1)? t : f; a >>= 1; } } if (!x.rep->virt) { unsigned short a = *s; for (int j = 0; j < BITSETBITS && a != 0; ++j) { *fmt++ = (a & 1)? t : f; a >>= 1; } *fmt++ = f; } else { unsigned short a = *s; unsigned short mask = ONES; unsigned short himask = (1 << (BITSETBITS - 1)) - 1; for (int j = 0; j < BITSETBITS && a != mask; ++j) { *fmt++ = (a & 1)? t : f; a = (a >> 1) & himask; mask = (mask >> 1) & himask; } *fmt++ = t; } *fmt++ = star; *fmt++ = 0; return fmtbase; } BitSet atoBitSet(const char* s, char f, char t, char star) return r { int sl = strlen(s); if (sl != 0) { r.rep = BitSetresize(r.rep, sl / BITSETBITS + 1); unsigned short* rs = r.rep->s; unsigned short a = 0; unsigned short m = 1; char lastch = 0; unsigned int i = 0; unsigned int l = 1; for(;;) { char ch = s[i]; if (ch == t) a |= m; else if (ch == star) { if (r.rep->virt = lastch == t) *rs = a | ~(m - 1); else *rs = a; break; } else if (ch != f) { *rs = a; break; } lastch = ch; if (++i == sl) { *rs = a; break; } else if (i % BITSETBITS == 0) { *rs++ = a; a = 0; m = 1; ++l; } else m <<= 1; } r.rep->len = l; trim(r.rep); } return; } ostream& operator << (ostream& s, const BitSet& x) { return s << BitSettoa(x); } int BitSet::OK() const { int v = rep != 0; // have a rep v &= rep->len <= rep->sz; // within bounds v &= rep->virt == 0 || rep->virt == 1; // valid virtual bit if (!v) error("invariant failure"); return v; } e if (i % BITSETBITS == 0) { *rs++ = a; a = 0; m = 1; ++l; } else m <<= 1; } r.rep->len = l; trim(r.rep); } return; } ostream& operator << (ostream& s, const BitSet& x) { return s << BitSettoa(x); } int BitSetlibg++/src/BitString.cc 644 473 0 122222 4677700045 10203 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* BitString class implementation */ #include #include #include #include #include #include volatile void BitString::error(const char* msg) const { (*lib_error_handler)("BitString", msg); } // globals BitStrRep _nilBitStrRep = { 0, 1, {0} }; BitString _nil_BitString; #define MINBitStrRep_SIZE 8 #define MAXBitStrRep_SIZE ((1 << (SHORTBITS - 1)) - 1) #ifndef MALLOC_MIN_OVERHEAD #define MALLOC_MIN_OVERHEAD 4 #endif #define ONES ((unsigned short)(~0L)) #define MAXBIT (1 << (BITSTRBITS - 1)) /* * bit manipulation utilities */ // break things up into .s indices and positions inline static int BitStr_len(int l) { return (unsigned)(l) / BITSTRBITS + 1; } // mask out low bits static inline unsigned short lmask(int p) { if (p <= 0) return ONES; else return ONES << p; } // mask out high bits static inline unsigned short rmask(int p) { int s = BITSTRBITS - 1 - p; if (s <= 0) return ONES; else return ONES >> s; } // mask out unused bits in last word of rep inline static void check_last(BitStrRep* r) { r->s[r->len / BITSTRBITS] &= ONES >> (BITSTRBITS - (r->len & (BITSTRBITS - 1))); } // merge bits from next word static inline unsigned short borrow_hi(const unsigned short a[], int ind, int maxind, int p) { if (ind < maxind) return (a[ind] >> p) | (a[ind+1] << (BITSTRBITS - p)); else return (a[ind] >> p); } // merge bits from prev word static inline unsigned short borrow_lo(const unsigned short a[], int ind, int minind, int p) { if (ind > minind) return (a[ind] << (BITSTRBITS - 1 - p)) | (a[ind-1] >> (p + 1)); else return (a[ind] << (BITSTRBITS - 1 - p)); } // same with bounds check (for masks shorter than patterns) static inline unsigned short safe_borrow_hi(const unsigned short a[], int ind, int maxind, int p) { if (ind > maxind) return 0; else if (ind == maxind) return(a[ind] >> p); else return (a[ind] >> p) | (a[ind+1] << (BITSTRBITS - p)); } static inline unsigned short safe_borrow_lo(const unsigned short a[], int ind, int minind, int p) { if (ind < minind) return 0; else if (ind == minind) return (a[ind] << (BITSTRBITS - 1 - p)); else return (a[ind] << (BITSTRBITS - 1 - p)) | (a[ind-1] >> (p + 1)); } // copy bits from a word boundary static inline void bit_copy(const unsigned short* ss, unsigned short* ds, int nbits) { if (ss != ds) { int n = (unsigned)(nbits) / BITSTRBITS; if (n > 0) bcopy((void*)ss, (void*)ds, n * sizeof(short)); unsigned short m = ONES << (nbits & (BITSTRBITS - 1)); ds[n] = (ss[n] & ~m) | (ds[n] & m); } } // clear bits from a word boundary static inline void bit_clear(unsigned short* ds, int nbits) { int n = (unsigned)(nbits) / BITSTRBITS; if (n > 0) bzero((void*)ds, n * sizeof(short)); ds[n] &= ONES << (nbits & (BITSTRBITS - 1)); } // Copy ss from starts to fences-1 into ds starting at startd. // This will work even if ss & ds overlap. // The g++ optimizer does very good things with the messy shift expressions! static void bit_transfer(const unsigned short* ss, int starts, int fences, unsigned short* ds, int startd) { if (starts >= fences || ss == 0 || (ss == ds && starts == startd)) return; int sind = BitStr_index(starts); int spos = BitStr_pos(starts); int dind = BitStr_index(startd); int dpos = BitStr_pos(startd); if (spos == 0 && dpos == 0) { bit_copy(&ss[sind], &ds[dind], fences - starts); return; } int ends = fences - 1; int endsind = BitStr_index(ends); int endspos = BitStr_pos(ends); int endd = startd + (ends - starts); int enddind = BitStr_index(endd); int enddpos = BitStr_pos(endd); if (dind == enddind) { if (sind == endsind) ds[dind] = (ds[dind] & ((ONES >> (BITSTRBITS - dpos)) | (ONES << (enddpos + 1)))) | (((ss[sind] >> spos) << dpos) & ~((ONES >> (BITSTRBITS - dpos)) | (ONES << (enddpos + 1)))); else ds[dind] = (ds[dind] & ((ONES >> (BITSTRBITS - dpos)) | (ONES << (enddpos + 1)))) | ((((ss[sind] >> spos) | (ss[sind+1] << (BITSTRBITS - spos))) << dpos) & ~((ONES >> (BITSTRBITS - dpos)) | (ONES << (enddpos + 1)))); return; } else if (sind == endsind) { unsigned short saveend = (ds[enddind] & (ONES << (enddpos + 1))) | (((ss[sind] << (BITSTRBITS - 1 - endspos)) >> (BITSTRBITS - 1 - enddpos)) & ~(ONES << (enddpos + 1))); ds[dind] = (ds[dind] & (ONES >> (BITSTRBITS - dpos))) | (((ss[sind] >> spos) << dpos) & ~(ONES >> (BITSTRBITS - dpos))); ds[enddind] = saveend; return; } unsigned short saveend = (ds[enddind] & (ONES << (enddpos + 1))) | ((((ss[endsind] << (BITSTRBITS - 1 - endspos)) | (ss[endsind-1] >> (endspos + 1))) >> (BITSTRBITS - 1 - enddpos)) & ~(ONES << (enddpos + 1))); unsigned short savestart = (ds[dind] & (ONES >> (BITSTRBITS - dpos))) | ((((ss[sind] >> spos) | (ss[sind+1] << (BITSTRBITS - spos))) << dpos) & ~(ONES >> (BITSTRBITS - dpos))); if (ds != ss || startd < starts) { int pos = spos - dpos; if (pos < 0) pos += BITSTRBITS; else ++sind; for (;;) // lag by one in case of overlaps { if (dind == enddind - 1) { ds[dind] = savestart; ds[enddind] = saveend; return; } else { unsigned short tmp = ss[sind] >> pos; if (++sind <= endsind) tmp |= ss[sind] << (BITSTRBITS - pos); ds[dind++] = savestart; savestart = tmp; } } } else { int pos = endspos - enddpos; if (pos <= 0) { pos += BITSTRBITS; --endsind; } for (;;) { if (enddind == dind + 1) { ds[enddind] = saveend; ds[dind] = savestart; return; } else { unsigned short tmp = ss[endsind] << (BITSTRBITS - pos); if (--endsind >= sind) tmp |= ss[endsind] >> pos; ds[enddind--] = saveend; saveend = tmp; } } } } // allocate a new rep; pad to near a power of two inline static BitStrRep* BSnew(int newlen) { unsigned int siz = sizeof(BitStrRep) + BitStr_len(newlen) * sizeof(short) + MALLOC_MIN_OVERHEAD; unsigned int allocsiz = MINBitStrRep_SIZE;; while (allocsiz < siz) allocsiz <<= 1; allocsiz -= MALLOC_MIN_OVERHEAD; if (allocsiz >= MAXBitStrRep_SIZE * sizeof(short)) (*lib_error_handler)("BitString", "Requested length out of range"); BitStrRep* rep = (BitStrRep *) new char[allocsiz]; bzero(rep, allocsiz); rep->sz = (allocsiz - sizeof(BitStrRep) + sizeof(short)) / sizeof(short); return rep; } BitStrRep* BStr_alloc(BitStrRep* old, const unsigned short* src, int startpos, int endp, int newlen) { if (old == &_nilBitStrRep) old = 0; if (newlen < 0) newlen = 0; int news = BitStr_len(newlen); BitStrRep* rep; if (old == 0 || news > old->sz) rep = BSnew(newlen); else rep = old; rep->len = newlen; if (src != 0 && endp > 0 && (src != rep->s || startpos > 0)) bit_transfer(src, startpos, endp, rep->s, 0); check_last(rep); if (old != rep && old != 0) delete old; return rep; } BitStrRep* BStr_resize(BitStrRep* old, int newlen) { BitStrRep* rep; if (newlen < 0) newlen = 0; int news = BitStr_len(newlen); if (old == 0 || old == &_nilBitStrRep) { rep = BSnew(newlen); } else if (news > old->sz) { rep = BSnew(newlen); bcopy(old->s, rep->s, BitStr_len(old->len) * sizeof(short)); delete old; } else rep = old; rep->len = newlen; check_last(rep); return rep; } BitStrRep* BStr_copy(BitStrRep* old, const BitStrRep* src) { BitStrRep* rep; if (old == src && old != &_nilBitStrRep) return old; if (old == &_nilBitStrRep) old = 0; if (src == &_nilBitStrRep) src = 0; if (src == 0) { if (old == 0) rep = BSnew(0); else rep = old; rep->len = 0; } else { int newlen = src->len; int news = BitStr_len(newlen); if (old == 0 || news > old->sz) { rep = BSnew(newlen); if (old != 0) delete old; } else rep = old; bcopy(src->s, rep->s, news * sizeof(short)); rep->len = newlen; } check_last(rep); return rep; } int operator == (const BitString& x, const BitString& y) { return x.rep->len == y.rep->len && bcmp((void*)x.rep->s, (void*)y.rep->s, BitStr_len(x.rep->len) * sizeof(short)) == 0; } int operator <= (const BitString& x, const BitString& y) { unsigned int xl = x.rep->len; unsigned int yl = y.rep->len; if (xl > yl) return 0; const unsigned short* xs = x.rep->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* ys = y.rep->s; while (xs < topx) { unsigned short a = *xs++; unsigned short b = *ys++; if ((a | b) != b) return 0; } return 1; } int operator < (const BitString& x, const BitString& y) { unsigned short xl = x.rep->len; unsigned short yl = y.rep->len; if (xl > yl) return 0; const unsigned short* xs = x.rep->s; const unsigned short* ys = y.rep->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* topy = &(ys[BitStr_len(yl)]); int one_diff = 0; while (xs < topx) { unsigned short a = *xs++; unsigned short b = *ys++; unsigned short c = a | b; if (c != b) return 0; else if (c != a) one_diff = 1; } if (one_diff) return 1; else { while (ys < topy) if (*ys++ != 0) return 1; return 0; } } int lcompare(const BitString& x, const BitString& y) { unsigned int xl = x.rep->len; unsigned int yl = y.rep->len; const unsigned short* xs = x.rep->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* ys = y.rep->s; const unsigned short* topy = &(ys[BitStr_len(yl)]); while (xs < topx && ys < topy) { unsigned short a = *xs++; unsigned short b = *ys++; if (a != b) { unsigned short mask = 1; for (;;) { unsigned short abit = (a & mask) != 0; unsigned short bbit = (b & mask) != 0; int diff = abit - bbit; if (diff != 0) return diff; else mask <<= 1; } } } return xl - yl; } int BitString::count(unsigned int b) const { check_last(rep); int xwds = BitStr_len(rep->len); int xlast = BitStr_pos(rep->len); int l = 0; const unsigned short* s = rep->s; const unsigned short* tops = &(s[xwds - 1]); unsigned short a; int i; if (b != 0) { while (s < tops) { a = *s++; for (i = 0; i < BITSTRBITS && a != 0; ++i) { if (a & 1) ++l; a >>= 1; } } a = *s; for (i = 0; i < xlast && a != 0; ++i) { if (a & 1) ++l; a >>= 1; } } else { unsigned short maxbit = 1 << (BITSTRBITS - 1); while (s < tops) { a = *s++; for (i = 0; i < BITSTRBITS; ++i) { if ((a & maxbit) == 0) ++l; a <<= 1; } } maxbit = 1 << (xlast - 1); a = *s; for (i = 0; i < xlast; ++i) { if ((a & maxbit) == 0) ++l; a <<= 1; } } return l; } BitStrRep* cmpl(const BitStrRep* src, BitStrRep* r) { r = BStr_copy(r, src); unsigned short* rs = r->s; unsigned short* topr = &(rs[BitStr_len(r->len)]); while (rs < topr) { unsigned short cmp = ~(*rs); *rs++ = cmp; } check_last(r); return r; } BitStrRep* and(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) { int xrsame = x == r; int yrsame = y == r; unsigned int xl = x->len; unsigned int yl = y->len; unsigned int rl = (xl <= yl)? xl : yl; r = BStr_resize(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[BitStr_len(rl)]); const unsigned short* xs = (xrsame)? rs : x->s; const unsigned short* ys = (yrsame)? rs : y->s; while (rs < topr) *rs++ = *xs++ & *ys++; check_last(r); return r; } BitStrRep* or(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) { unsigned int xl = x->len; unsigned int yl = y->len; unsigned int rl = (xl >= yl)? xl : yl; int xrsame = x == r; int yrsame = y == r; r = BStr_resize(r, rl); unsigned short* rs = r->s; const unsigned short* xs = (xrsame)? rs : x->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* ys = (yrsame)? rs : y->s; const unsigned short* topy = &(ys[BitStr_len(yl)]); if (xl <= yl) { while (xs < topx) *rs++ = *xs++ | *ys++; if (rs != ys) while (ys < topy) *rs++ = *ys++; } else { while (ys < topy) *rs++ = *xs++ | *ys++; if (rs != xs) while (xs < topx) *rs++ = *xs++; } check_last(r); return r; } BitStrRep* xor(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) { unsigned int xl = x->len; unsigned int yl = y->len; unsigned int rl = (xl >= yl)? xl : yl; int xrsame = x == r; int yrsame = y == r; r = BStr_resize(r, rl); unsigned short* rs = r->s; const unsigned short* xs = (xrsame)? rs : x->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* ys = (yrsame)? rs : y->s; const unsigned short* topy = &(ys[BitStr_len(yl)]); if (xl <= yl) { while (xs < topx) *rs++ = *xs++ ^ *ys++; if (rs != ys) while (ys < topy) *rs++ = *ys++; } else { while (ys < topy) *rs++ = *xs++ ^ *ys++; if (rs != xs) while (xs < topx) *rs++ = *xs++; } check_last(r); return r; } BitStrRep* diff(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) { unsigned int xl = x->len; unsigned int yl = y->len; int xrsame = x == y; int yrsame = y == r; r = BStr_resize(r, xl); unsigned short* rs = r->s; const unsigned short* xs = (xrsame)? rs : x->s; const unsigned short* topx = &(xs[BitStr_len(xl)]); const unsigned short* ys = (yrsame)? rs : y->s; const unsigned short* topy = &(ys[BitStr_len(yl)]); if (xl <= yl) { while (xs < topx) *rs++ = *xs++ & ~(*ys++); } else { while (ys < topy) *rs++ = *xs++ & ~(*ys++); if (rs != xs) while (xs < topx) *rs++ = *xs++; } check_last(r); return r; } BitStrRep* cat(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) { unsigned int xl = x->len; unsigned int yl = y->len; unsigned int rl = xl + yl; int xrsame = x == r; int yrsame = y == r; if (yrsame) { if (xrsame) { r = BStr_resize(r, rl); bit_transfer(r->s, 0, yl, r->s, xl); } else { BitStrRep* tmp = BStr_copy(0, y); r = BStr_resize(r, rl); bit_copy(x->s, r->s, xl); bit_transfer(tmp->s, 0, yl, r->s, xl); delete tmp; } } else { r = BStr_resize(r, rl); if (!xrsame) bit_copy(x->s, r->s, xl); bit_transfer(y->s, 0, yl, r->s, xl); } check_last(r); return r; } BitStrRep* cat(const BitStrRep* x, unsigned int bit, BitStrRep* r) { unsigned int xl = x->len; int xrsame = x == r; r = BStr_resize(r, xl+1); if (!xrsame) bit_copy(x->s, r->s, xl); if (bit) r->s[BitStr_index(xl)] |= (1 << (BitStr_pos(xl))); else r->s[BitStr_index(xl)] &= ~(1 << (BitStr_pos(xl))); check_last(r); return r; } BitStrRep* lshift(const BitStrRep* x, int s, BitStrRep* r) { int xrsame = x == r; int xl = x->len; int rl = xl + s; if (s == 0) r = BStr_copy(r, x); else if (rl <= 0) { r = BStr_resize(r, 0); r->len = 0; r->s[0] = 0; } else if (s > 0) { r = BStr_resize(r, rl); const unsigned short* xs = (xrsame)? r->s : x->s; bit_transfer(xs, 0, xl, r->s, s); bit_clear(r->s, s); } else if (xrsame) { r = BStr_resize(r, xl); r->len = rl; bit_transfer(r->s, -s, xl, r->s, 0); } else { r = BStr_resize(r, rl); bit_transfer(x->s, -s, xl, r->s, 0); } check_last(r); return r; } void BitString::set(int p) { if (p < 0) error("Illegal bit index"); if (p >= rep->len) rep = BStr_resize(rep, p + 1); rep->s[BitStr_index(p)] |= (1 << (BitStr_pos(p))); } void BitString::assign(int p, unsigned int bit) { if (p < 0) error("Illegal bit index"); if (p >= rep->len) rep = BStr_resize(rep, p + 1); if (bit) rep->s[BitStr_index(p)] |= (1 << (BitStr_pos(p))); else rep->s[BitStr_index(p)] &= ~(1 << (BitStr_pos(p))); } void BitString::clear(int p) { if (p < 0) error("Illegal bit index"); if (p >= rep->len) rep = BStr_resize(rep, p + 1); rep->s[BitStr_index(p)] &= ~(1 << (BitStr_pos(p))); } void BitString::clear() { if (rep == &_nilBitStrRep) return; bit_clear(rep->s, rep->len); } void BitString::set() { if (rep == &_nilBitStrRep) return; unsigned short* s = rep->s; unsigned short* tops = &(s[BitStr_len(rep->len)]); while (s < tops) *s++ = ONES; check_last(rep); } void BitString::invert(int p) { if (p < 0) error("Illegal bit index"); if (p >= rep->len) rep = BStr_resize(rep, p + 1); rep->s[BitStr_index(p)] ^= (1 << (BitStr_pos(p))); } void BitString::set(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); if (to >= rep->len) rep = BStr_resize(rep, to+1); int ind1 = BitStr_index(from); int pos1 = BitStr_pos(from); int ind2 = BitStr_index(to); int pos2 = BitStr_pos(to); unsigned short* s = &(rep->s[ind1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (ind2 == ind1) *s |= m1 & m2; else { *s++ |= m1; unsigned short* top = &(rep->s[ind2]); *top |= m2; while (s < top) *s++ = ONES; } } void BitString::clear(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); if (to >= rep->len) rep = BStr_resize(rep, to+1); int ind1 = BitStr_index(from); int pos1 = BitStr_pos(from); int ind2 = BitStr_index(to); int pos2 = BitStr_pos(to); unsigned short* s = &(rep->s[ind1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (ind2 == ind1) *s &= ~(m1 & m2); else { *s++ &= ~m1; unsigned short* top = &(rep->s[ind2]); *top &= ~m2; while (s < top) *s++ = 0; } } void BitString::invert(int from, int to) { if (from < 0 || from > to) error("Illegal bit index"); if (to >= rep->len) rep = BStr_resize(rep, to+1); int ind1 = BitStr_index(from); int pos1 = BitStr_pos(from); int ind2 = BitStr_index(to); int pos2 = BitStr_pos(to); unsigned short* s = &(rep->s[ind1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (ind2 == ind1) *s ^= m1 & m2; else { *s++ ^= m1; unsigned short* top = &(rep->s[ind2]); *top ^= m2; while (s < top) { unsigned short cmp = ~(*s); *s++ = cmp; } } } int BitString::test(int from, int to) const { if (from < 0 || from > to || from >= rep->len) return 0; int ind1 = BitStr_index(from); int pos1 = BitStr_pos(from); int ind2 = BitStr_index(to); int pos2 = BitStr_pos(to); if (to >= rep->len) { ind2 = BitStr_index(rep->len - 1); pos2 = BitStr_pos(rep->len - 1); } const unsigned short* s = &(rep->s[ind1]); unsigned short m1 = lmask(pos1); unsigned short m2 = rmask(pos2); if (ind2 == ind1) return (*s & m1 & m2) != 0; else { if (*s++ & m1) return 1; unsigned short* top = &(rep->s[ind2]); if (*top & m2) return 1; while (s < top) if (*s++ != 0) return 1; return 0; } } int BitString::next(int p, unsigned int b) const { if (++p >= rep->len) return -1; int ind = BitStr_index(p); int pos = BitStr_pos(p); int l = BitStr_len(rep->len); int j = ind; const unsigned short* s = rep->s; unsigned short a = s[j] >> pos; int i = pos; if (b != 0) { for (; i < BITSTRBITS && a != 0; ++i) { if (a & 1) return j * BITSTRBITS + i; a >>= 1; } for (++j; j < l; ++j) { a = s[j]; for (i = 0; i < BITSTRBITS && a != 0; ++i) { if (a & 1) return j * BITSTRBITS + i; a >>= 1; } } return -1; } else { int last = BitStr_pos(rep->len); if (j == l - 1) { for (; i < last; ++i) { if ((a & 1) == 0) return j * BITSTRBITS + i; a >>= 1; } return -1; } for (; i < BITSTRBITS; ++i) { if ((a & 1) == 0) return j * BITSTRBITS + i; a >>= 1; } for (++j; j < l - 1; ++j) { a = s[j]; if (a != ONES) { for (i = 0; i < BITSTRBITS; ++i) { if ((a & 1) == 0) return j * BITSTRBITS + i; a >>= 1; } } } a = s[j]; for (i = 0; i < last; ++i) { if ((a & 1) == 0) return j * BITSTRBITS + i; a >>= 1; } return -1; } } int BitString::previous(int p, unsigned int b) const { if (--p < 0) return -1; int ind = BitStr_index(p); int pos = BitStr_pos(p); const unsigned short* s = rep->s; if (p >= rep->len) { ind = BitStr_index(rep->len - 1); pos = BitStr_pos(rep->len - 1); } int j = ind; unsigned short a = s[j]; int i = pos; unsigned short maxbit = 1 << pos; if (b != 0) { for (; i >= 0 && a != 0; --i) { if (a & maxbit) return j * BITSTRBITS + i; a <<= 1; } maxbit = 1 << (BITSTRBITS - 1); for (--j; j >= 0; --j) { a = s[j]; for (i = BITSTRBITS - 1; i >= 0 && a != 0; --i) { if (a & maxbit) return j * BITSTRBITS + i; a <<= 1; } } return -1; } else { if (a != ONES) { for (; i >= 0; --i) { if ((a & maxbit) == 0) return j * BITSTRBITS + i; a <<= 1; } } maxbit = 1 << (BITSTRBITS - 1); for (--j; j >= 0; --j) { a = s[j]; if (a != ONES) { for (i = BITSTRBITS - 1; i >= 0; --i) { if ((a & maxbit) == 0) return j * BITSTRBITS + i; a <<= 1; } } } return -1; } } int BitString::search(int startx, int lengthx, const unsigned short* ys, int starty, int lengthy) const { const unsigned short* xs = rep->s; int ylen = lengthy - starty; int righty = lengthy - 1; int rev = startx < 0; if (rev) { int leftx = 0; int rightx = lengthx + startx; startx = rightx - ylen + 1; if (ylen == 0) return startx; if (starty < 0 || righty < 0 || startx < 0 || startx >= lengthx) return -1; int xind = BitStr_index(startx); int xpos = BitStr_pos(startx); int yind = BitStr_index(starty); int ypos = BitStr_pos(starty); int rightxind = BitStr_index(rightx); unsigned short x = borrow_hi(xs, xind, rightxind, xpos); int rightyind = BitStr_index(righty); int rightypos = BitStr_pos(righty); unsigned short y = borrow_hi(ys, yind, rightyind, ypos); unsigned short ymask; if (yind == rightyind) ymask = rmask(rightypos); else if (yind+1 == rightyind) ymask = rmask(BITSTRBITS - ypos + rightypos + 1); else ymask = ONES; int p = startx; for (;;) { if ((x & ymask) == y) { int xi = xind; int yi = yind; for (;;) { if (++yi > rightyind || ++xi > rightxind) return p; unsigned short tx = borrow_hi(xs, xi, rightxind, xpos); unsigned short ty = borrow_hi(ys, yi, rightyind, ypos); if (yi == rightyind) tx &= rmask(rightypos); else if (yi+1 == rightyind) tx &= rmask(BITSTRBITS - ypos + rightypos + 1); if (tx != ty) break; } } if (--p < leftx) return -1; if (--xpos < 0) { xpos = BITSTRBITS - 1; --xind; } x = borrow_hi(xs, xind, rightxind, xpos); } } else { int rightx = lengthx - 1; if (ylen == 0) return startx; if (starty < 0 || righty < 0 || startx < 0 || startx >= lengthx) return -1; int xind = BitStr_index(startx); int xpos = BitStr_pos(startx); int yind = BitStr_index(starty); int ypos = BitStr_pos(starty); int rightxind = BitStr_index(rightx); unsigned short x = borrow_hi(xs, xind, rightxind, xpos); unsigned short nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos); int rightyind = BitStr_index(righty); int rightypos = BitStr_pos(righty); unsigned short y = borrow_hi(ys, yind, rightyind, ypos); unsigned short ymask; if (yind == rightyind) ymask = rmask(rightypos); else if (yind+1 == rightyind) ymask = rmask(BITSTRBITS - ypos + rightypos + 1); else ymask = ONES; int p = startx; for (;;) { if ((x & ymask) == y) { int xi = xind; int yi = yind; for (;;) { if (++yi > rightyind || ++xi > rightxind) return p; unsigned short tx = borrow_hi(xs, xi, rightxind, xpos); unsigned short ty = borrow_hi(ys, yi, rightyind, ypos); if (yi == rightyind) tx &= rmask(rightypos); else if (yi+1 == rightyind) tx &= rmask(BITSTRBITS - ypos + rightypos + 1); if (tx != ty) break; } } if (++p > rightx) return -1; if (++xpos == BITSTRBITS) { xpos = 0; x = xs[++xind]; nextx = (xind >= rightxind) ? 0 : xs[xind+1]; } else { x >>= 1; if (nextx & 1) x |= MAXBIT; nextx >>= 1; } } } } int BitPattern::search(const unsigned short* xs, int startx, int lengthx) const { const unsigned short* ys = pattern.rep->s; const unsigned short* ms = mask.rep->s; int righty = pattern.rep->len - 1; int rightm = mask.rep->len - 1; int rev = startx < 0; if (rev) { int leftx = 0; int rightx = lengthx + startx; startx = rightx - righty; if (righty < 0) return startx; if (startx < 0 || startx >= lengthx) return -1; int xind = BitStr_index(startx); int xpos = BitStr_pos(startx); int rightxind = BitStr_index(rightx); int rightmind = BitStr_index(rightm); int rightyind = BitStr_index(righty); unsigned short x = safe_borrow_hi(xs, xind, rightxind, xpos); unsigned short m = safe_borrow_hi(ms, 0, rightmind, 0); unsigned short y = safe_borrow_hi(ys, 0, rightyind, 0) & m; int p = startx; for (;;) { if ((x & m) == y) { int xi = xind; int yi = 0; for (;;) { if (++yi > rightyind || ++xi > rightxind) return p; unsigned short tm = safe_borrow_hi(ms, yi, rightmind, 0); unsigned short ty = safe_borrow_hi(ys, yi, rightyind, 0); unsigned short tx = safe_borrow_hi(xs, xi, rightxind, xpos); if ((tx & tm) != (ty & tm)) break; } } if (--p < leftx) return -1; if (--xpos < 0) { xpos = BITSTRBITS - 1; --xind; } x = safe_borrow_hi(xs, xind, rightxind, xpos); } } else { int rightx = lengthx - 1; if (righty < 0) return startx; if (startx < 0 || startx >= lengthx) return -1; int xind = BitStr_index(startx); int xpos = BitStr_pos(startx); int rightxind = BitStr_index(rightx); int rightmind = BitStr_index(rightm); int rightyind = BitStr_index(righty); unsigned short x = safe_borrow_hi(xs, xind, rightxind, xpos); unsigned short m = safe_borrow_hi(ms, 0, rightmind, 0); unsigned short y = safe_borrow_hi(ys, 0, rightyind, 0) & m; unsigned short nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos); int p = startx; for (;;) { if ((x & m) == y) { int xi = xind; int yi = 0; for (;;) { if (++yi > rightyind || ++xi > rightxind) return p; unsigned short tm = safe_borrow_hi(ms, yi, rightmind, 0); unsigned short ty = safe_borrow_hi(ys, yi, rightyind, 0); unsigned short tx = safe_borrow_hi(xs, xi, rightxind, xpos); if ((tx & tm) != (ty & tm)) break; } } if (++p > rightx) return -1; if (++xpos == BITSTRBITS) { xpos = 0; x = xs[++xind]; nextx = (xind >= rightxind) ? 0 : xs[xind+1]; } else { x >>= 1; if (nextx & 1) x |= MAXBIT; nextx >>= 1; } } } } int BitString::match(int startx, int lengthx, int exact, const unsigned short* ys, int starty, int yl) const { const unsigned short* xs = rep->s; int ylen = yl - starty; int righty = yl - 1; int rightx; int rev = startx < 0; if (rev) { rightx = lengthx + startx; startx = rightx - ylen + 1; if (exact && startx != 0) return 0; } else { rightx = lengthx - 1; if (exact && rightx - startx != righty) return 0; } if (ylen == 0) return 1; if (righty < 0 || startx < 0 || startx >= lengthx) return 0; int xi = BitStr_index(startx); int xpos = BitStr_pos(startx); int yi = BitStr_index(starty); int ypos = BitStr_pos(starty); int rightxind = BitStr_index(rightx); int rightyind = BitStr_index(righty); int rightypos = BitStr_pos(righty); for (;;) { unsigned short x = borrow_hi(xs, xi, rightxind, xpos); unsigned short y = borrow_hi(ys, yi, rightyind, ypos); if (yi == rightyind) x &= rmask(rightypos); else if (yi+1 == rightyind) x &= rmask(BITSTRBITS - ypos + rightypos + 1); if (x != y) return 0; else if (++yi > rightyind || ++xi > rightxind) return 1; } } int BitPattern::match(const unsigned short* xs, int startx, int lengthx, int exact) const { const unsigned short* ys = pattern.rep->s; int righty = pattern.rep->len - 1; unsigned short* ms = mask.rep->s; int rightm = mask.rep->len - 1; int rightx; int rev = startx < 0; if (rev) { rightx = lengthx + startx; startx = rightx - righty; if (exact && startx != 0) return 0; } else { rightx = lengthx - 1; if (exact && rightx - startx != righty) return 0; } if (righty < 0) return 1; if (startx < 0 || startx >= lengthx) return 0; int xind = BitStr_index(startx); int xpos = BitStr_pos(startx); int yind = 0; int rightxind = BitStr_index(rightx); int rightyind = BitStr_index(righty); int rightmind = BitStr_index(rightm); for(;;) { unsigned short m = safe_borrow_hi(ms, yind, rightmind, 0); unsigned short x = safe_borrow_hi(xs, xind, rightxind, xpos) & m; unsigned short y = safe_borrow_hi(ys, yind, rightyind, 0) & m; if (x != y) return 0; else if (++yind > rightyind || ++xind > rightxind) return 1; } } void BitSubString::operator = (const BitString& y) { if (&S == &_nil_BitString) return; BitStrRep* targ = S.rep; int ylen = y.rep->len; int sl = targ->len - len + ylen; if (y.rep == targ || ylen > len) { BitStrRep* oldtarg = targ; targ = BStr_alloc(0, 0, 0, 0, sl); bit_transfer(oldtarg->s, 0, pos, targ->s, 0); bit_transfer(y.rep->s, 0, ylen, targ->s, pos); bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + ylen); delete oldtarg; } else if (len == ylen) bit_transfer(y.rep->s, 0, len, targ->s, pos); else if (ylen < len) { bit_transfer(y.rep->s, 0, ylen, targ->s, pos); bit_transfer(targ->s, pos+len, targ->len, targ->s, pos + ylen); targ->len = sl; } check_last(targ); S.rep = targ; } void BitSubString::operator = (const BitSubString& y) { if (&S == &_nil_BitString) return; BitStrRep* targ = S.rep; if (len == 0 || pos >= targ->len) return; int sl = targ->len - len + y.len; if (y.S.rep == targ || y.len > len) { BitStrRep* oldtarg = targ; targ = BStr_alloc(0, 0, 0, 0, sl); bit_copy(oldtarg->s, targ->s, pos); bit_transfer(y.S.rep->s, y.pos, y.pos+y.len, targ->s, pos); bit_transfer(oldtarg->s, pos+len, oldtarg->len, targ->s, pos + y.len); delete oldtarg; } else if (len == y.len) bit_transfer(y.S.rep->s, y.pos, y.pos+y.len, targ->s, pos); else if (y.len < len) { bit_transfer(y.S.rep->s, y.pos, y.pos+y.len, targ->s, pos); bit_transfer(targ->s, pos+len, targ->len, targ->s, pos + y.len); targ->len = sl; } check_last(targ); S.rep = targ; } BitSubString BitString::at(int first, int len) { return _substr(first, len); } BitSubString BitString::before(int pos) { return _substr(0, pos); } BitSubString BitString::after(int pos) { return _substr(pos + 1, rep->len - (pos + 1)); } BitSubString BitString::at(const BitString& y, int startpos) { int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len); return _substr(first, y.rep->len); } BitSubString BitString::before(const BitString& y, int startpos) { int last = search(startpos, rep->len, y.rep->s, 0, y.rep->len); return _substr(0, last); } BitSubString BitString::after(const BitString& y, int startpos) { int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len); if (first >= 0) first += y.rep->len; return _substr(first, rep->len - first); } BitSubString BitString::at(const BitSubString& y, int startpos) { int first = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); return _substr(first, y.len); } BitSubString BitString::before(const BitSubString& y, int startpos) { int last = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); return _substr(0, last); } BitSubString BitString::after(const BitSubString& y, int startpos) { int first = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); if (first >= 0) first += y.len; return _substr(first, rep->len - first); } BitSubString BitString::at(const BitPattern& r, int startpos) { int first = r.search(rep->s, startpos, rep->len); return _substr(first, r.pattern.rep->len); } BitSubString BitString::before(const BitPattern& r, int startpos) { int first = r.search(rep->s, startpos, rep->len); return _substr(0, first); } BitSubString BitString::after(const BitPattern& r, int startpos) { int first = r.search(rep->s, startpos, rep->len); if (first >= 0) first += r.pattern.rep->len; return _substr(first, rep->len - first); } BitString common_prefix(const BitString& x, const BitString& y, int startpos) return r { unsigned int xl = x.rep->len; unsigned int yl = y.rep->len; int startx, starty; if (startpos < 0) { startx = xl + startpos; starty = yl + startpos; } else startx = starty = startpos; if (startx < 0 || startx >= xl || starty < 0 || starty >= yl) return; const unsigned short* xs = &(x.rep->s[BitStr_index(startx)]); unsigned short a = *xs++; int xp = startx; const unsigned short* ys = &(y.rep->s[BitStr_index(starty)]); unsigned short b = *ys++; int yp = starty; for(; xp < xl && yp < yl; ++xp, ++yp) { unsigned short xbit = 1 << (BitStr_pos(xp)); unsigned short ybit = 1 << (BitStr_pos(yp)); if (((a & xbit) == 0) != ((b & ybit) == 0)) break; if (xbit == MAXBIT) a = *xs++; if (ybit == MAXBIT) b = *ys++; } r.rep = BStr_alloc(0, x.rep->s, startx, xp, xp - startx); } BitString common_suffix(const BitString& x, const BitString& y, int startpos) return r; { unsigned int xl = x.rep->len; unsigned int yl = y.rep->len; int startx, starty; if (startpos < 0) { startx = xl + startpos; starty = yl + startpos; } else startx = starty = startpos; if (startx < 0 || startx >= xl || starty < 0 || starty >= yl) return; const unsigned short* xs = &(x.rep->s[BitStr_index(startx)]); unsigned short a = *xs--; int xp = startx; const unsigned short* ys = &(y.rep->s[BitStr_index(starty)]); unsigned short b = *ys--; int yp = starty; for(; xp >= 0 && yp >= 0; --xp, --yp) { unsigned short xbit = 1 << (BitStr_pos(xp)); unsigned short ybit = 1 << (BitStr_pos(yp)); if (((a & xbit) == 0) != ((b & ybit) == 0)) break; if (xbit == 1) a = *xs--; if (ybit == 1) b = *ys--; } r.rep = BStr_alloc(0, x.rep->s, xp+1, startx+1, startx - xp); } BitString reverse(const BitString& x) return r { unsigned int yl = x.rep->len; BitStrRep* y = BStr_resize(0, yl); if (yl > 0) { const unsigned short* ls = x.rep->s; unsigned short lm = 1; unsigned short* rs = &(y->s[BitStr_index(yl - 1)]); unsigned short rm = 1 << (BitStr_pos(yl - 1)); for (unsigned int l = 0; l < yl; ++l) { if (*ls & lm) *rs |= rm; if (lm == MAXBIT) { ++ls; lm = 1; } else lm <<= 1; if (rm == 1) { --rs; rm = MAXBIT; } else rm >>= 1; } } r.rep = y; } extern AllocRing _libgxx_fmtq; const char* BitStringtoa(const BitString& x, char f, char t) { int wrksiz = x.length() + 2; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* fmt = fmtbase; unsigned int xl = x.rep->len; const unsigned short* s = x.rep->s; unsigned short a = 0; for (unsigned int i = 0; i < xl; ++i) { if (i % BITSTRBITS == 0) a = *s++; *fmt++ = (a & 1)? t : f; a >>= 1; } *fmt = 0; return fmtbase; } BitString atoBitString(const char* s, char f, char t) return res { int sl = strlen(s); BitStrRep* r = BStr_resize(0, sl); if (sl != 0) { unsigned int rl = 0; unsigned short* rs = r->s; unsigned short a = 0; unsigned short m = 1; unsigned int i = 0; for(;;) { char ch = s[i]; if (ch != t && ch != f) { *rs = a; break; } ++rl; if (ch == t) a |= m; if (++i == sl) { *rs = a; break; } else if (i % BITSTRBITS == 0) { *rs++ = a; a = 0; m = 1; } else m <<= 1; } r = BStr_resize(r, rl); } res.rep = r; } ostream& operator << (ostream& s, const BitString& x) { return s << BitStringtoa(x); } const char* BitPatterntoa(const BitPattern& p, char f,char t,char x) { unsigned int pl = p.pattern.rep->len; unsigned int ml = p.mask.rep->len; unsigned int l = (pl <= ml)? pl : ml; int wrksiz = l + 2; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* fmt = fmtbase; const unsigned short* ps = p.pattern.rep->s; const unsigned short* ms = p.mask.rep->s; unsigned short a = 0; unsigned short m = 0; for (unsigned int i = 0; i < l; ++i) { if (i % BITSTRBITS == 0) { a = *ps++; m = *ms++; } if (m & 1) *fmt++ =(a & 1)? t : f; else *fmt++ = x; a >>= 1; m >>= 1; } *fmt = 0; return fmtbase; } BitPattern atoBitPattern(const char* s, char f,char t,char x) return r { int sl = strlen(s); if (sl != 0) { unsigned int rl = 0; r.pattern.rep = BStr_resize(r.pattern.rep, sl); r.mask.rep = BStr_resize(r.mask.rep, sl); unsigned short* rs = r.pattern.rep->s; unsigned short* ms = r.mask.rep->s; unsigned short a = 0; unsigned short b = 0; unsigned short m = 1; unsigned int i = 0; for(;;) { char ch = s[i]; if (ch != t && ch != f && ch != x) { *rs = a; *ms = b; break; } ++rl; if (ch == t) { a |= m; b |= m; } else if (ch == f) { b |= m; } if (++i == sl) { *rs = a; *ms = b; break; } else if (i % BITSTRBITS == 0) { *rs++ = a; *ms++ = b; a = 0; b = 0; m = 1; } else m <<= 1; } r.pattern.rep = BStr_resize(r.pattern.rep, rl); r.mask.rep = BStr_resize(r.mask.rep, rl); } return r; } ostream& operator << (ostream& s, const BitPattern& x) { return s << BitPatterntoa(x); } int BitString::OK() const { int v = rep != 0; // have a rep; v &= BitStr_len(rep->len) <= rep->sz; // within allocated size if (!v) error("invariant failure"); return v; } int BitSubString::OK() const { int v = S.OK(); // valid BitString v &= pos >= 0 && len >= 0; // valid indices v &= pos + len <= S.rep->len; // within bounds of targ if (!v) S.error("BitSubString invariant failure"); return v; } int BitPattern::OK() const { int v = pattern.OK() && mask.OK(); if (!v) pattern.error("BitPattern invariant failure"); return v; } v &= BitStr_len(rep->len) <= rep->sz; // within allocated size if (!v) error("invariant failure"); return v; } int BitSubString::OK() const { int v = S.OK(); // valid BitString v &= pos >= 0 && len >= 0; // valid indices v &= pos + len <= S.rep->len; // within bounds of targ if (!v) S.error("BitSubString invariant failure"); returlibg++/src/Complex.cc 644 473 0 12137 4677700045 7670 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include // error handling void default_Complex_error_handler(const char* msg) { cerr << "Fatal Complex arithmetic error. " << msg << "\n"; exit(1); } one_arg_error_handler_t Complex_error_handler = default_Complex_error_handler; one_arg_error_handler_t set_Complex_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Complex_error_handler; Complex_error_handler = f; return old; } void Complex::error(const char* msg) const { (*Complex_error_handler)(msg); } Complex /* const */ operator / (const Complex& x, const Complex& y) { double den = norm(y); if (den == 0.0) x.error ("Attempted division by zero."); return Complex((x.real() * y.real() + x.imag() * y.imag()) / den, (x.imag() * y.real() - x.real() * y.imag()) / den); } Complex /* const */ operator / (double x, const Complex& y) { double den = norm(y); if (den == 0.0) y.error ("Attempted division by zero."); return Complex((x * y.real()) / den, -(x * y.imag()) / den); } Complex /* const */ operator / (const Complex& x, double y) { if (y == 0.0) x.error ("Attempted division by zero."); return Complex(x.real() / y, x.imag() / y); } Complex& Complex::operator /= (const Complex& y) { double den = norm(y); if (den == 0.0) error ("Attempted division by zero."); double r = (re * y.real() + im * y.imag()) / den; im = (im * y.real() - re * y.imag()) / den; re = r; return *this; } Complex& Complex::operator /= (double y) { if (y == 0.0) error ("Attempted division by zero."); re /= y; im /= y; return *this; } Complex /* const */ exp(const Complex& x) { double r = exp(x.real()); return Complex(r * cos(x.imag()), r * sin(x.imag())); } Complex /* const */ cosh(const Complex& x) { return Complex(cos(x.imag()) * cosh(x.real()), sin(x.imag()) * sinh(x.real())); } Complex /* const */ sinh(const Complex& x) { return Complex(cos(x.imag()) * sinh(x.real()), sin(x.imag()) * cosh(x.real())); } Complex /* const */ cos(const Complex& x) { return Complex(cos(x.real()) * cosh(x.imag()), -sin(x.real()) * sinh(x.imag())); } Complex /* const */ sin(const Complex& x) { return Complex(sin(x.real()) * cosh(x.imag()), cos(x.real()) * sinh(x.imag())); } Complex /* const */ log(const Complex& x) { double h = hypot(x.real(), x.imag()); if (h <= 0.0) x.error("attempted log of zero magnitude number."); return Complex(log(h), atan2(x.imag(), x.real())); } Complex /* const */ pow(const Complex& x, const Complex& p) { if (p.real() == 0.0 && p.imag() == 0.0) return Complex(1.0, 0.0); else if (x.real() == 0.0 && x.imag() == 0.0) return Complex(0.0, 0.0); else { double h = hypot(x.real(), x.imag()); if (h <= 0.0) x.error("attempted power of zero magnitude number."); double lr = exp(log(h) * p.real()); double li = atan2(x.imag(), x.real()) * p.imag(); return Complex(lr * cos(li), lr * sin(li)); } } Complex /* const */ sqrt(const Complex& x) { if (x.real() == 0.0 && x.imag() == 0.0) return Complex(0.0, 0.0); else { double s = sqrt((abs(x.real()) + hypot(x.real(), x.imag())) * 0.5); double d = (x.imag() / s) * 0.5; if (x.real() > 0.0) return Complex(s, d); else if (x.imag() >= 0.0) return Complex(d, s); else return Complex(-d, -s); } } Complex /* const */ pow(const Complex& x, long p) { if (p == 0) return Complex(1.0, 0.0); else if (x == 0.0) return Complex(0.0, 0.0); else { Complex res(1.0, 0.0); Complex b = x; if (p < 0) { p = -p; b = 1.0 / b; } for(;;) { if (p & 1) res *= b; if ((p >>= 1) == 0) return res; else b *= b; } } } ostream& operator << (ostream& s, const Complex& x) { return s << "(" << x.real() << ", " << x.imag() << ")" ; } istream& operator >> (istream& s, Complex& x) { double r, i; char ch; s >> WS; s.get(ch); if (ch == '(') { s >> r; s >> WS; s.get(ch); if (ch == ',') { s >> i; s >> WS; s .get(ch); } else i = 0; if (ch != ')') s.set(_bad); } else { s.unget(ch); s >> r; i = 0; } x = Complex(r, i); return s; } } ostream& operator << (ostream& s, const Complex& x) { return s << "(" << x.real() << ", " << x.imag() << ")" ; } istream& operator >> (istream& s, Complex& x) { double r, i; char ch; s >> WS; s.get(ch); if (ch == '(') { s >> r; s >> WS; s.get(ch); if (ch == ',') { s >> i; s >> WS; s .get(ch); } else i = 0; if (ch != ')') s.set(_bad); libg++/src/File.cc 644 473 0 24605 4677700045 7143 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include #include // needed to determine values of O_RDONLY... // error handlers void verbose_File_error_handler(const char* msg) { perror(msg); errno = 0; } void quiet_File_error_handler(const char*) { errno = 0; } void fatal_File_error_handler(const char* msg) { perror(msg); exit(1); } one_arg_error_handler_t File_error_handler = verbose_File_error_handler; one_arg_error_handler_t set_File_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = File_error_handler; File_error_handler = f; return old; } /* Opening files. open(filename, io_mode, access_mode) is done via system open command since fopen doesn't handle all of the cases possible with sys open. After a successful open, fdopen is called to attach an _iobuf to the file descriptor. All this requires a few decoding routines that can translate among our enumerated types, system flags, and fopen modes. */ enum sys_open_cmd_io_mode // These should be correct for most systems { sio_read = O_RDONLY, sio_write = O_WRONLY, sio_readwrite = O_RDWR, sio_append = O_APPEND }; enum sys_open_cmd_access_mode { sa_create = O_CREAT, sa_truncate = O_TRUNC, sa_createonly = O_EXCL | O_CREAT }; static int open_cmd_arg(io_mode i, access_mode a) // decode modes { int arg; switch(i) { case io_readonly: arg = sio_read; break; case io_writeonly: arg = sio_write; break; case io_readwrite: arg = sio_readwrite; break; case io_appendonly: arg = sio_append | sio_write; break; case io_append: arg = sio_append | sio_readwrite; break; default: return -1; }; switch(a) { case a_createonly: return arg | sa_createonly; case a_create: return arg | sa_create | sa_truncate; case a_useonly: return arg; case a_use: return arg | sa_create; default: return -1; } } static char* fopen_cmd_arg(io_mode i) { switch(i) { case io_readonly: return "r"; case io_writeonly: return "w"; case io_readwrite: return "r+"; case io_appendonly:return "a"; case io_append: return "a+"; default: return 0; } } void File::initialize() { fp = 0; nm = 0; stat = 0; state = _bad; rw = 0; } // reset class vars after open // fp->_flag inspection is isolated here void File::reinitialize(const char* filename) { if (filename != 0) setname(filename); else if (fp == stdin) setname("(stdin)"); else if (fp == stdout) setname("(stdout)"); else if (fp == stderr) setname("(stderr)"); else if (rw & 4) setname("(string)"); else setname(0); if (fp != 0) { state = _good; if (fp->_flag & (_IOREAD|_IORW)) rw |= 01; if (fp->_flag & (_IOWRT|_IORW|_IOAPPEND)) rw |= 02; check_state(); } else { set(_fail); set(_bad); error(); } } File& File::open(const char* filename, io_mode m, access_mode a) { close(); int open_arg = open_cmd_arg(m, a); if (open_arg != -1) { int fd = ::open(filename, open_arg, 0666); if (fd >= 0) fp = fdopen(fd, fopen_cmd_arg(m)); } reinitialize(filename); return *this; } File& File::open(const char* filename, const char* m) { close(); fp = fopen(filename, m); reinitialize(filename); return *this; } File& File::open(FILE* fileptr) { close(); fp = fileptr; reinitialize(0); return *this; } File& File::open(int filedesc, io_mode m) { close(); fp = fdopen(filedesc, fopen_cmd_arg(m)); reinitialize(0); return *this; } File& File::close() { if (fp != 0) { if (rw & 4) // we own the iobuf, kill it delete fp; else if (fp == stdin || fp == stdout || fp == stderr) flush(); else fclose(fp); } fp = 0; rw = 0; set(_bad); return *this; } File& File::remove() { close(); return failif (nm == 0 || unlink(nm) != 0); } File::File() { initialize(); } File::File(const char* filename, io_mode m, access_mode a) { initialize(); open(filename, m, a); } File::File(const char* filename, const char* m) { initialize(); open(filename, m); } File::File(int filedesc, io_mode m) { initialize(); open(filedesc, m); } File::File(FILE* fileptr) { initialize(); open(fileptr); } File::File(int sz, char* buf, io_mode m) { if (m != io_readonly && m != io_writeonly) (*File_error_handler) ("invalid io_mode for string IO"); initialize(); rw = 4; fp = new _iobuf; #ifndef _NFILE fp->_file = 255; // any illegal value #else fp->_file = _NFILE-1; // The last filedescriptor... _bufendtab[fp->_file] = (BUFEND_ENTRY_TYPE)buf+sz-1; #endif fp->_ptr = fp->_base = buf; #ifdef HAVE_BUFSIZ fp->_bufsiz = sz; #endif if (m == io_readonly) { int len = 0; while (len < sz && buf[len] != 0) ++len; if (len == sz) buf[sz - 1] = 0; // force null-termination! fp->_cnt = len; fp->_flag = _IOREAD | _IOSTRG | _IOMYBUF; } else { bzero(buf, sz); // so any result will be null-terminated fp->_cnt = sz - 1; // leave at least one null at end fp->_flag = _IOWRT | _IOSTRG | _IOMYBUF; } reinitialize(0); } File::~File() { delete(nm); close(); } void File::setname(const char* newname) { if (nm == newname) return; if (nm != 0) delete(nm); if (newname != 0) { nm = new char[strlen(newname) + 1]; strcpy(nm, newname); } else nm = 0; } File& File::setbuf(int buffer_kind) { if (!is_open()) { set(_fail); return *this; } switch(buffer_kind) { case _IOFBF: #ifdef HAVE_SETVBUF setvbuf(fp, 0, _IOFBF, 0); #endif break; case _IONBF: ::setbuf(fp, 0); break; case _IOLBF: #ifdef HAVE_SETLINEBUF setlinebuf(fp); #else #ifdef HAVE_SETVBUF setvbuf(fp, 0, _IOLBF, 0); #endif #endif break; default: break; } return *this; } File& File::setbuf(int size, char* buf) { if (!is_open()) { set(_fail); return *this; } #ifdef HAVE_SETVBUF setvbuf(fp, buf, _IOFBF, size); #else setbuffer(fp, buf, size); #endif return *this; } void File::error() { check_state(); set(_fail); if (errno != 0) { char error_string[400]; strcpy(error_string, "\nerror in File "); if (nm != 0) strcat(error_string, nm); (*File_error_handler)(error_string); } } //------------------------------------------------------------------ void File::check_state() // ensure fp & state agree about eof { if (fp != 0) { if (feof(fp)) set(_eof); else unset(_eof); if (ferror(fp)) set(_bad); } } File& File::put(const char* s) { return failif(!writable() || fputs(s, fp) == EOF); } File& File::get(char* s, int n, char terminator) { if (!readable()) { set(_fail); return *this; } char ch; stat = --n; if (n > 0 && (get(ch))) { if (ch == terminator) { unget(ch); stat= 0; // This is not an error condition ! } else { *s++ = ch; --n; while (n > 0 && (get(ch))) { if (ch == terminator) { unget(ch); break; } else { *s++ = ch; --n; } } } } *s = 0; return failif((stat != 0) && ((stat -= n) == 0)); } File& File::getline(char* s, int n, char terminator) { if (!readable()) { set(_fail); return *this; } char ch; stat = --n; while (n > 0 && (get(ch))) { --n; if ((*s++ = ch) == terminator) break; } *s = 0; return failif((stat != 0) && ((stat -= n) == 0)); } // from Doug Schmidt // This should probably be a page size.... #define CHUNK_SIZE 512 /* Reads an arbitrarily long input line terminated by a user-specified TERMINATOR. Super-nifty trick using recursion avoids unnecessary calls to NEW! */ char *File::readline (int chunk_number, char terminator) { char buf[CHUNK_SIZE]; register char *bufptr = buf; register char *ptr; char ch; int continu; while ((continu = !!get(ch)) && ch != terminator) /* fill the current buffer */ { *bufptr++ = ch; if (bufptr - buf >= CHUNK_SIZE) /* prepend remainder to ptr buffer */ { if (ptr = readline (chunk_number + 1, terminator)) for (; bufptr != buf; *--ptr = *--bufptr); return ptr; } } if (!continu && bufptr == buf) return NULL; int size = (chunk_number * CHUNK_SIZE + bufptr - buf) + 1; if (ptr = new char[stat = size]) { for (*(ptr += (size - 1)) = '\0'; bufptr != buf; *--ptr = *--bufptr) ; return ptr; } else return NULL; } /* Reads an arbitrarily long input line terminated by TERMINATOR. This routine allocates its own memory, so the user should only supply the address of a (char *). */ File& File::gets(char **s, char terminator) { if (!readable()) { set(_fail); return *this; } return failif(!(*s = readline (0, terminator))); } File& File::scan(const char* fmt ...) { if (readable()) { va_list args; va_start(args, fmt); stat = _doscan(fp, fmt, args); va_end(args); failif(stat <= 0); } return *this; } File& File::form(const char* fmt ...) { va_list args; va_start(args, fmt); #ifndef HAVE_VPRINTF stat = _doprnt(fmt, args, fp); #ifdef HAVE_VOID_DOPRNT stat = ferror(fp) ? -1 : 0; #endif #else stat = vfprintf(fp, fmt, args); #endif va_end(args); failif(stat < 0); return *this; } tor))); } File& File::scan(const char* fmt ...) { if (readable()) { va_list args; va_start(args, fmt); slibg++/src/Fix.cc 644 473 0 26035 4677700045 7011 // // Fix.cc : variable length fixed point data type class functions // #include #include #include #include // default parameters uint16 Fix_default_length = 16; int Fix_default_print_width = 8; Fix_peh Fix_overflow_handler = Fix_overflow_saturate; _Frep _Frep_0 = { 16, 1, 1, { 0 } }; _Frep _Frep_m1 = { 16, 1, 1, { 0x8000 } }; _Frep _Frep_quotient_bump = { 16, 1, 1, { 0x4000 } }; // error handling void default_Fix_error_handler(const char* msg) { cerr << "Fix: " << msg << "\n"; abort(); } void default_Fix_range_error_handler(const char* msg) { cerr << "Fix: range error in " << msg << "\n"; //abort(); } one_arg_error_handler_t Fix_error_handler = default_Fix_error_handler, Fix_range_error_handler = default_Fix_range_error_handler; one_arg_error_handler_t set_Fix_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Fix_error_handler; Fix_error_handler = f; return old; } one_arg_error_handler_t set_Fix_range_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = Fix_range_error_handler; Fix_range_error_handler = f; return old; } void Fix::error(const char* msg) { (*Fix_error_handler)(msg); } void Fix::range_error(const char* msg) { (*Fix_range_error_handler)(msg); } // _Frep allocation and initialization functions inline _Fix _new_Fix(uint16 len) { int siz = (((uint32 )len + 15) >> 4); if (siz <= 0) siz = 1; unsigned int allocsiz = (sizeof(_Frep) + (siz - 1) * sizeof(uint16)); _Fix z = (_Fix)(new char[allocsiz]); bzero(z, allocsiz); z->len = len; z->siz = siz; z->ref = 1; return z; } _Fix new_Fix(uint16 len) { return _new_Fix(len); } _Fix new_Fix(uint16 len, _Fix x) { _Fix z = _new_Fix(len); return copy(x,z); } _Fix new_Fix(uint16 len, double d) { _Fix z = _new_Fix(len); if ( d == _Fix_max_value ) { z->s[0] = 0x7fff; for ( int i=1; i < z->siz; i++ ) z->s[i] = 0xffff; } else if ( d < _Fix_min_value || d > _Fix_max_value ) (*Fix_range_error_handler)("declaration"); else { if (d < 0) d += 2.0; d *= 32768; for ( int i=0; i < z->siz; i++ ) { z->s[i] = (uint16 )d; d -= z->s[i]; d *= 65536; } if ( d >= 32768 ) z->s[z->siz-1]++; } mask(z); return z; } // convert to a double double value(Fix& x) { double d = 0.0; for ( int i=x.rep->siz-1; i >= 0; i-- ) { d += x.rep->s[i]; d *= 1./65536.; } d *= 2.; return d < 1. ? d : d - 2.; } // extract mantissa to Integer Integer mantissa(Fix& x) { Integer a = 1, b=1; for ( int i=0; i < x.rep->siz; i++ ) { a = (a << 16) + x.rep->s[i]; b <<= 16; } return a-b; } // comparison functions inline static int docmp(uint16* x, uint16* y, int siz) { int diff = (int16 )*x - (int16 )*y; while ( --siz && !diff ) diff = (int32 )(uint32 )*++x - (int32 )(uint32 )*++y; return diff; } inline static int docmpz(uint16* x, int siz) { while ( siz-- ) if ( *x++ ) return 1; return 0; } int compare(_Fix x, _Fix y) { if ( x->siz == y->siz ) return docmp(x->s, y->s, x->siz); else { int r; _Fix longer, shorter; if ( x->siz > y->siz ) { longer = x; shorter = y; r = 1; } else { longer = y; shorter = x; r = -1; } int diff = docmp(x->s, y->s, shorter->siz); if ( diff ) return diff; else if ( docmpz(&longer->s[shorter->siz], longer->siz-shorter->siz) ) return r; else return 0; } } // arithmetic functions _Fix add(_Fix x, _Fix y, _Fix r) { uint16 xsign = x->s[0], ysign = y->s[0]; _Fix longer, shorter; if ( x->len >= y->len ) longer = x, shorter = y; else longer = y, shorter = x; if ( r == NULL ) r = new_Fix(longer->len); for ( int i=r->siz-1; i >= longer->siz; i-- ) r->s[i] = 0; for ( ; i >= shorter->siz; i-- ) r->s[i] = longer->s[i]; uint32 sum = 0, carry = 0; for ( ; i >= 0; i-- ) { sum = carry + (uint32 )x->s[i] + (uint32 )y->s[i]; carry = sum >> 16; r->s[i] = sum; } if ( (xsign ^ sum) & (ysign ^ sum) & 0x8000 ) (*Fix_overflow_handler)(r); return r; } _Fix subtract(_Fix x, _Fix y, _Fix r) { uint16 xsign = x->s[0], ysign = y->s[0]; _Fix longer, shorter; if ( x->len >= y->len ) longer = x, shorter = y; else longer = y, shorter = x; if ( r == NULL ) r = new_Fix(longer->len); for ( int i=r->siz-1; i >= longer->siz; i-- ) r->s[i] = 0; for ( ; i >= shorter->siz; i-- ) r->s[i] = (longer == x ? x->s[i] : -y->s[i]); int16 carry = 0; uint32 sum = 0; for ( ; i >= 0; i-- ) { sum = (int32 )carry + (uint32 )x->s[i] - (uint32 )y->s[i]; carry = sum >> 16; r->s[i] = sum; } if ( (xsign ^ sum) & (~ysign ^ sum) & 0x8000 ) (*Fix_overflow_handler)(r); return r; } _Fix multiply(_Fix x, _Fix y, _Fix r) { if ( r == NULL ) r = new_Fix(x->len + y->len); int xsign = x->s[0] & 0x8000, ysign = y->s[0] & 0x8000; Fix X(x->len), Y(y->len); if ( xsign ) x = negate(x,X.rep); if ( ysign ) y = negate(y,Y.rep); for ( int i=0; i < r->siz; i++ ) r->s[i] = 0; for ( i=x->siz-1; i >= 0; i-- ) { uint32 carry = 0; for ( int j=y->siz-1; j >= 0; j-- ) { int k = i + j + 1; uint32 a = (uint32 )x->s[i] * (uint32 )y->s[j]; uint32 b = ((a << 1) & 0xffff) + carry; if ( k < r->siz ) { b += r->s[k]; r->s[k] = b; } if ( k < r->siz + 1 ) carry = (a >> 15) + (b >> 16); } r->s[i] = carry; } if ( xsign != ysign ) negate(r,r); return r; } _Fix multiply(_Fix x, int y, _Fix r) { if ( y != (int16 )y ) (*Fix_range_error_handler)("multiply by int -- int too large"); if ( r == NULL ) r = new_Fix(x->len); for ( int i=r->siz-1; i >= x->siz; i-- ) r->s[i] = 0; int32 a, carry = 0; for ( ; i > 0; i-- ) { a = (int32 )(uint32 )x->s[i] * y + carry; r->s[i] = a; carry = a >> 16; // assumes arithmetic right shift } a = (int32 )(int16 )x->s[0] * y + carry; r->s[0] = a; a &= 0xffff8000L; if ( a != 0xffff8000L && a != 0L ) { r->s[0] = 0x8000 ^ x->s[0] ^ y; (*Fix_overflow_handler)(r); } return r; } _Fix divide(_Fix x, _Fix y, _Fix q, _Fix r) { int xsign = x->s[0] & 0x8000, ysign = y->s[0] & 0x8000; if ( q == NULL ) q = new_Fix(x->len); copy(&_Frep_0,q); if ( r == NULL ) r = new_Fix(x->len + y->len - 1); if ( xsign ) negate(x,r); else copy(x,r); Fix Y(y->len); y = ( ysign ? negate(y,Y.rep) : copy(y,Y.rep) ); if ( !compare(y) ) (*Fix_range_error_handler)("division -- division by zero"); else if ( compare(x,y) >= 0 ) if ( compare(x,y) == 0 && xsign ^ ysign != 0 ) { copy(&_Frep_m1,q); copy(&_Frep_0,r); } else (*Fix_range_error_handler)("division"); else { _Fix t; Fix S(r->len), W(q->len,&_Frep_quotient_bump); for ( int i=1; i < q->len; i++ ) { shift(y,-1,y); subtract(r,y,S.rep); int s_status = compare(S.rep); if ( s_status == 0 ) { t = r, r = S.rep, S.rep = t; break; } else if ( s_status > 0 ) { t = r, r = S.rep, S.rep = t; add(q,W.rep,q); } shift(W.rep,-1,W.rep); } if ( xsign ^ ysign ) negate(q,q); } return q; } _Fix shift(_Fix x, int y, _Fix r) { if ( y == 0 ) return x; else if ( r == NULL ) r = new_Fix(x->len); int ay = abs((long) y), ayh = ay >> 4, ayl = ay & 0x0f; int xl, u, ilow, ihigh; uint16 *rs, *xsl, *xsr; if ( y > 0 ) { rs = r->s; xsl = x->s + ayh; xsr = xsl + 1; xl = ayl; u = 1; ihigh = x->siz - ayh - 1; ilow = 0; } else { rs = &r->s[r->siz - 1]; xsr = &x->s[r->siz - 1] - ayh; xsl = xsr - 1; xl = 16 - ayl; u = -1; ihigh = r->siz - ayh - 1; ilow = ihigh - x->siz; } int xr = 16 - xl; uint16 xrmask = 0xffffL >> xr; for ( int i=0; i < ilow; i++, rs+=u, xsl+=u, xsr+=u ) *rs = 0; for ( ; i < ihigh; i++, rs+=u, xsl+=u, xsr+=u ) *rs = (*xsl << xl) + ((*xsr >> xr) & xrmask); *rs = (y > 0 ? (*xsl << xl) : ((*xsr >> xr) & xrmask)); rs += u; for ( ; ++i < r->siz; rs+=u ) *rs = 0; return r; } _Fix negate(_Fix x, _Fix r) { if ( r == NULL ) r = new_Fix(x->len); uint32 carry = 1; for ( int i=r->siz-1; i >= x->siz; i-- ) r->s[i] = 0; for ( ; i >= 0; i-- ) { uint32 a = (uint16 )~x->s[i] + carry; // bug work-around r->s[i] = a; carry = a >> 16; } return r; } // io functions Fix atoF(const char* a, int len) { return Fix(len,atof(a)); } extern AllocRing _libgxx_fmtq; char* Ftoa(Fix& x, int width) { int wrksiz = width + 2; char *s = (char *) _libgxx_fmtq.alloc(wrksiz); char format[100]; double val = value(x); if (val < 0) sprintf(format,"%%%d.%dlf",width-2,width-3); else sprintf(format," %%%d.%dlf",width-2,width-3); sprintf(s,format,val); return s; } extern Obstack _libgxx_io_ob; Fix Fix::operator %= (int y) { Fix r((int )rep->len + y, *this); return *this = r; } istream& operator >> (istream& s, Fix& y) { int got_one = 0; if (!s.readable()) { s.set(_bad); return s; } char sign = 0, point = 0; char ch; s >> WS; if (!s.good()) { s.set(_bad); return s; } while (s.get(ch)) { if (ch == '-') { if (sign == 0) { sign = 1; _libgxx_io_ob.grow(ch); } else break; } if (ch == '.') { if (point == 0) { point = 1; _libgxx_io_ob.grow(ch); } else break; } else if (ch >= '0' && ch <= '9') { got_one = 1; _libgxx_io_ob.grow(ch); } else break; } char * p = (char*)(_libgxx_io_ob.finish(0)); if (s.good()) s.unget(ch); if (!got_one) s.error(); else y = atoF(p); _libgxx_io_ob.free(p); return s; } void show(Fix& x) { cout << "len = " << x.rep->len << "\n"; cout << "siz = " << x.rep->siz << "\n"; cout << "ref = " << x.rep->ref << "\n"; cout << "man = " << Itoa(mantissa(x),16,4*x.rep->siz) << "\n"; cout << "val = " << value(x) << "\n"; } // parameter setting operations Fix_peh set_overflow_handler(Fix_peh new_handler) { Fix_peh old_handler = Fix_overflow_handler; Fix_overflow_handler = new_handler; return old_handler; } int Fix_set_default_length(int newlen) { uint16 oldlen = Fix_default_length; if ( newlen < _Fix_min_length || newlen > _Fix_max_length ) (*Fix_error_handler)("illegal length in Fix_set_default_length"); Fix_default_length = newlen; return oldlen; } // overflow handlers void Fix_overflow_saturate(_Fix& r) { if ( (int16 )r->s[0] > 0 ) { r->s[0] = 0x8000; for ( int i=1; i < r->siz; i++ ) r->s[i] = 0; } else { r->s[0] = 0x7fff; for ( int i=1; i < r->siz; i++ ) r->s[i] = 0xffff; mask(r); } } void Fix_overflow_wrap(_Fix& r) {} void Fix_overflow_warning_saturate(_Fix& r) { Fix_overflow_warning(r); Fix_overflow_saturate(r); } void Fix_overflow_warning(_Fix& r) { cerr << "Fix: overflow warning\n"; } void Fix_overflow_error(_Fix& r) { cerr << "Fix: overflow error\n"; abort(); } ] > 0 ) { r->s[0] = 0x8000; for ( int i=1; i < r->siz; i++ ) r->s[i] = 0; } else { r->s[0] = 0x7fff; for ( int i=1; i < r->siz; i++ ) r->s[i] = 0xffff; mask(r); } } void Fix_overflow_wrap(_Fix& r) {} void Fix_overflow_warning_saturate(_Fix& r) { Fix_overflow_warning(r); Fix_overflow_saturate(r); } void Fix_overflow_warning(_Fix& r) { cerr << "Fix: overflow warning\n"; } void Fix_overflow_error(_Fix& r) { cerr << "Fix: overflibg++/src/Rational.cc 644 473 0 13264 4677700046 10035 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include volatile void Rational::error(const char* msg) const { (*lib_error_handler)("Rational", msg); } static const Integer _Int_One(1); void Rational::normalize() { int s = sign(den); if (s == 0) error("Zero denominator."); else if (s < 0) { den.negate(); num.negate(); } Integer g = gcd(num, den); if (ucompare(g, _Int_One) != 0) { num /= g; den /= g; } } void add(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); add(r.num, r.den, r.num); mul(x.den, y.den, r.den); } else { Integer tmp; mul(x.den, y.num, tmp); mul(x.num, y.den, r.num); add(r.num, tmp, r.num); mul(x.den, y.den, r.den); } r.normalize(); } void sub(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); sub(r.num, r.den, r.num); mul(x.den, y.den, r.den); } else { Integer tmp; mul(x.den, y.num, tmp); mul(x.num, y.den, r.num); sub(r.num, tmp, r.num); mul(x.den, y.den, r.den); } r.normalize(); } void mul(const Rational& x, const Rational& y, Rational& r) { mul(x.num, y.num, r.num); mul(x.den, y.den, r.den); r.normalize(); } void div(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); } else { Integer tmp; mul(x.num, y.den, tmp); mul(y.num, x.den, r.den); r.num = tmp; } r.normalize(); } Rational operator - (const Rational& x) return r(x) { r.negate(); } Rational abs(const Rational& x) return r(x) { if (sign(r.num) < 0) r.negate(); } Rational sqr(const Rational& x) return r { mul(x.num, x.num, r.num); mul(x.den, x.den, r.den); r.normalize(); } void Rational::invert() { Integer tmp = num; num = den; den = tmp; int s = sign(den); if (s == 0) error("Zero denominator."); else if (s < 0) { den.negate(); num.negate(); } } int compare(const Rational& x, const Rational& y) { int xsgn = sign(x.num); int ysgn = sign(y.num); int d = xsgn - ysgn; if (d == 0 && xsgn != 0) d = compare(x.num * y.den, x.den * y.num); return d; } Rational::Rational(double x) { num = 0; den = 1; if (x != 0.0) { int neg = x < 0; if (neg) x = -x; const long shift = 15; // a safe shift per step const double width = 32768.0; // = 2^shift const int maxiter = 20; // ought not be necessary, but just in case, // max 300 bits of precision int expt; double mantissa = frexp(x, &expt); long exponent = expt; double intpart; int k = 0; while (mantissa != 0.0 && k++ < maxiter) { mantissa *= width; mantissa = modf(mantissa, &intpart); num <<= shift; num += (long)intpart; exponent -= shift; } if (exponent > 0) num <<= exponent; else if (exponent < 0) den <<= -exponent; if (neg) num.negate(); } normalize(); } Integer floor(const Rational& x) return q { Integer r; divide(x.num, x.den, q, r); if (sign(x.num) < 0 && sign(r) != 0) q--; } Integer ceil(const Rational& x) return q { Integer r; divide(x.num, x.den, q, r); if (sign(x.num) >= 0 && sign(r) != 0) q++; } Integer round(const Rational& x) return q { Integer r; divide(x.num, x.den, q, r); r <<= 1; if (ucompare(r, x.den) >= 0) { if (sign(x.num) >= 0) q++; else q--; } } Integer trunc(const Rational& x) { return x.num / x.den ; } Rational pow(const Rational& x, const Integer& y) { long yy = long(y); return pow(x, yy); } // power: no need to normalize since num & den already relatively prime Rational pow(const Rational& x, long y) return r { if (y >= 0) { pow(x.num, y, r.num); pow(x.den, y, r.den); } else { y = -y; pow(x.num, y, r.den); pow(x.den, y, r.num); if (sign(r.den) < 0) { r.num.negate(); r.den.negate(); } } } ostream& operator << (ostream& s, const Rational& y) { if (y.den == 1) s << Itoa(y.num); else { s << Itoa(y.num); s << "/"; s << Itoa(y.den); } return s; } istream& operator >> (istream& s, Rational& y) { s >> y.num; if (s) { char ch = 0; s.get(ch); if (ch == '/') { s >> y.den; y.normalize(); } else { s.unget(ch); y.den = 1; } } return s; } int Rational::OK() const { int v = num.OK() && den.OK(); // have valid num and denom v &= sign(den) > 0; // denominator positive; v &= ucompare(gcd(num, den), _Int_One) == 0; // relatively prime if (!v) error("invariant failure"); return v; } & operator >> (istream& s, Rational& y) { s >> y.num; if (s) { char ch = 0; s.get(ch); if (ch == '/') { s >> y.den; y.normalize(); } else { s.unget(ch); y.den = 1; } } return s; } int Rational::OK() const { int v = num.OK() && den.OK(); // have valid num and denolibg++/src/Integer.cc 644 473 0 131011 4677700046 7670 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* Some of the following algorithms are very loosely based on those from MIT C-Scheme bignum.c, which is Copyright (c) 1987 Massachusetts Institute of Technology with other guidance from Knuth, vol. 2 Thanks to the creators of the algorithms. */ #include #include #include #include #include #include #include #include /* Sizes of shifts for multiple-precision arithmetic. These should not be changed unless Integer representation as unsigned shorts is changed in the implementation files. */ #define I_SHIFT SHORTBITS #define I_RADIX ((unsigned long)(1L << I_SHIFT)) #define I_MAXNUM ((unsigned long)((I_RADIX - 1))) #define I_MINNUM ((unsigned long)(I_RADIX >> 1)) #define I_POSITIVE 1 #define I_NEGATIVE 0 /* All routines assume SHORT_PER_LONG > 1 */ #define SHORT_PER_LONG ((LONGBITS + SHORTBITS - 1) / SHORTBITS) #define CHAR_PER_LONG ((LONGBITS + CHARBITS - 1) / CHARBITS) /* minimum and maximum sizes for an IntRep */ #define MINIntRep_SIZE 16 #define MAXIntRep_SIZE I_MAXNUM #ifndef MALLOC_MIN_OVERHEAD #define MALLOC_MIN_OVERHEAD 4 #endif // utilities to extract and transfer bits // get low bits inline static unsigned short extract(unsigned long x) { return x & I_MAXNUM; } // transfer high bits to low inline static unsigned long down(unsigned long x) { return (x >> I_SHIFT) & I_MAXNUM; } // transfer low bits to high inline static unsigned long up(unsigned long x) { return x << I_SHIFT; } // compare two equal-length reps inline static int docmp(const unsigned short* x, const unsigned short* y, int l) { int diff = 0; const unsigned short* xs = &(x[l]); const unsigned short* ys = &(y[l]); while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); return diff; } // figure out max length of result of +, -, etc. inline static int calc_len(int len1, int len2, int pad) { return (len1 >= len2)? len1 + pad : len2 + pad; } // ensure len & sgn are correct inline static void Icheck(IntRep* rep) { int l = rep->len; const unsigned short* p = &(rep->s[l]); while (l > 0 && *--p == 0) --l; if ((rep->len = l) == 0) rep->sgn = I_POSITIVE; } // zero out the end of a rep inline static void Iclear_from(IntRep* rep, int p) { unsigned short* cp = &(rep->s[p]); const unsigned short* cf = &(rep->s[rep->len]); while(cp < cf) *cp++ = 0; } // copy parts of a rep static inline void scpy(const unsigned short* src, unsigned short* dest,int nb) { while (--nb >= 0) *dest++ = *src++; } // make sure an argument is valid static inline void nonnil(const IntRep* rep) { if (rep == 0) (*lib_error_handler)("Integer", "operation on uninitialized Integer"); } // allocate a new Irep. Pad to something close to a power of two. inline static IntRep* Inew(int newlen) { unsigned int siz = sizeof(IntRep) + newlen * sizeof(short) + MALLOC_MIN_OVERHEAD; unsigned int allocsiz = MINIntRep_SIZE; while (allocsiz < siz) allocsiz <<= 1; // find a power of 2 allocsiz -= MALLOC_MIN_OVERHEAD; if (allocsiz >= MAXIntRep_SIZE * sizeof(short)) (*lib_error_handler)("Integer", "Requested length out of range"); IntRep* rep = (IntRep *) new char[allocsiz]; rep->sz = (allocsiz - sizeof(IntRep) + sizeof(short)) / sizeof(short); return rep; } // allocate: use the bits in src if non-null, clear the rest IntRep* Ialloc(IntRep* old, const unsigned short* src, int srclen, int newsgn, int newlen) { IntRep* rep; if (old == 0 || newlen > old->sz) rep = Inew(newlen); else rep = old; rep->len = newlen; rep->sgn = newsgn; scpy(src, rep->s, srclen); Iclear_from(rep, srclen); if (old != rep && old != 0) delete old; return rep; } // allocate and clear IntRep* Icalloc(IntRep* old, int newlen) { IntRep* rep; if (old == 0 || newlen > old->sz) { if (old != 0) delete old; rep = Inew(newlen); } else rep = old; rep->len = newlen; rep->sgn = I_POSITIVE; Iclear_from(rep, 0); return rep; } // reallocate IntRep* Iresize(IntRep* old, int newlen) { IntRep* rep; unsigned short oldlen; if (old == 0) { oldlen = 0; rep = Inew(newlen); rep->sgn = I_POSITIVE; } else { oldlen = old->len; if (newlen > old->sz) { rep = Inew(newlen); scpy(old->s, rep->s, oldlen); rep->sgn = old->sgn; delete old; } else rep = old; } rep->len = newlen; Iclear_from(rep, oldlen); return rep; } // same, for straight copy IntRep* Icopy(IntRep* old, const IntRep* src) { if (old == src) return old; IntRep* rep; if (src == 0) { if (old == 0) rep = Inew(0); else { rep = old; Iclear_from(rep, 0); } rep->len = 0; rep->sgn = I_POSITIVE; } else { int newlen = src->len; if (old == 0 || newlen > old->sz) { if (old != 0) delete old; rep = Inew(newlen); } else rep = old; rep->len = newlen; rep->sgn = src->sgn; scpy(src->s, rep->s, newlen); } return rep; } // allocate & copy space for a long IntRep* Icopy_long(IntRep* old, long x) { unsigned short src[SHORT_PER_LONG]; unsigned long u; int newsgn; if (newsgn = (x >= 0)) u = x; else u = -x; unsigned short srclen = 0; while (u != 0) { src[srclen++] = extract(u); u = down(u); } IntRep* rep; if (old == 0 || srclen > old->sz) { if (old != 0) delete old; rep = Inew(srclen); } else rep = old; rep->len = srclen; rep->sgn = newsgn; scpy(src, rep->s, srclen); return rep; } // special case for zero -- it's worth it! IntRep* Icopy_zero(IntRep* old) { IntRep* rep; if (old == 0) rep = Inew(0); else rep = old; rep->len = 0; rep->sgn = I_POSITIVE; return rep; } // special case for 1 or -1 IntRep* Icopy_one(IntRep* old, int newsgn) { IntRep* rep; if (old == 0 || 1 > old->sz) { if (old != 0) delete old; rep = Inew(1); } else rep = old; rep->sgn = newsgn; rep->len = 1; rep->s[0] = 1; return rep; } // convert to a legal two's complement long if possible // if too big, return most negative/positive value long Itolong(const IntRep* rep) { if (rep->len > SHORT_PER_LONG) return (rep->sgn == I_POSITIVE) ? MAXLONG : MINLONG; else if (rep->len == 0) return 0; else if (rep->len < SHORT_PER_LONG) { unsigned long a = rep->s[rep->len-1]; if (SHORT_PER_LONG > 2) // normally optimized out { for (int i = rep->len - 2; i >= 0; --i) a = up(a) | rep->s[i]; } return (rep->sgn == I_POSITIVE)? a : -((long)a); } else { unsigned long a = rep->s[SHORT_PER_LONG - 1]; if (a >= I_MINNUM) return (rep->sgn == I_POSITIVE) ? MAXLONG : MINLONG; else { a = up(a) | rep->s[SHORT_PER_LONG - 2]; if (SHORT_PER_LONG > 2) { for (int i = SHORT_PER_LONG - 3; i >= 0; --i) a = up(a) | rep->s[i]; } return (rep->sgn == I_POSITIVE)? a : -((long)a); } } } // test whether op long() will work. // careful about asymmetry between MINLONG & MAXLONG int Iislong(const IntRep* rep) { int l = rep->len; if (l < SHORT_PER_LONG) return 1; else if (l > SHORT_PER_LONG) return 0; else if (rep->s[SHORT_PER_LONG - 1] < I_MINNUM) return 1; else if (rep->sgn == I_NEGATIVE && rep->s[SHORT_PER_LONG - 1] == I_MINNUM) { for (int i = 0; i < SHORT_PER_LONG - 1; ++i) if (rep->s[i] != 0) return 0; return 1; } else return 0; } // convert to a double double Itodouble(const IntRep* rep) { double d = 0.0; double bound = HUGE / 2.0; for (int i = rep->len - 1; i >= 0; --i) { unsigned short a = I_RADIX >> 1; while (a != 0) { if (d >= bound) return (rep->sgn == I_NEGATIVE) ? -HUGE : HUGE; d *= 2.0; if (rep->s[i] & a) d += 1.0; a >>= 1; } } if (rep->sgn == I_NEGATIVE) return -d; else return d; } // see whether op double() will work- // have to actually try it in order to find out // since otherwise might trigger fp exception int Iisdouble(const IntRep* rep) { double d = 0.0; double bound = HUGE / 2.0; for (int i = rep->len - 1; i >= 0; --i) { unsigned short a = I_RADIX >> 1; while (a != 0) { if (d > bound || (d == bound && (i > 0 || (rep->s[i] & a)))) return 0; d *= 2.0; if (rep->s[i] & a) d += 1.0; a >>= 1; } } return 1; } // real division of num / den double ratio(const Integer& num, const Integer& den) { Integer q, r; divide(num, den, q, r); double d1 = double(q); if (d1 == HUGE || d1 == -HUGE || sign(r) == 0) return d1; else // use as much precision as available for fractional part { double d2 = 0.0; double d3 = 0.0; double bound = HUGE / 2.0; int cont = 1; for (int i = den.rep->len - 1; i >= 0 && cont; --i) { unsigned short a = I_RADIX >> 1; while (a != 0) { if (d2 >= bound) { cont = 0; break; } d2 *= 2.0; if (den.rep->s[i] & a) d2 += 1.0; if (i < r.rep->len) { d3 *= 2.0; if (r.rep->s[i] & a) d3 += 1.0; } a >>= 1; } } if (sign(r) < 0) d3 = -d3; return d1 + d3 / d2; } } // comparison functions int compare(const IntRep* x, const IntRep* y) { int diff = x->sgn - y->sgn; if (diff == 0) { diff = x->len - y->len; if (diff == 0) diff = docmp(x->s, y->s, x->len); if (x->sgn == I_NEGATIVE) diff = -diff; } return diff; } int ucompare(const IntRep* x, const IntRep* y) { int diff = x->len - y->len; if (diff == 0) { int l = x->len; const unsigned short* xs = &(x->s[l]); const unsigned short* ys = &(y->s[l]); while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); } return diff; } int compare(const IntRep* x, long y) { int xl = x->len; int xsgn = x->sgn; if (y == 0) { if (xl == 0) return 0; else if (xsgn == I_NEGATIVE) return -1; else return 1; } else { int ysgn = y >= 0; unsigned long uy = (ysgn)? y : -y; int diff = xsgn - ysgn; if (diff == 0) { diff = xl - SHORT_PER_LONG; if (diff <= 0) { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } diff = xl - yl; if (diff == 0) diff = docmp(x->s, tmp, xl); } } if (xsgn == I_NEGATIVE) diff = -diff; return diff; } } int ucompare(const IntRep* x, long y) { int xl = x->len; if (y == 0) return xl; else { unsigned long uy = (y >= 0)? y : -y; int diff = xl - SHORT_PER_LONG; if (diff <= 0) { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } diff = xl - yl; if (diff == 0) diff = docmp(x->s, tmp, xl); } return diff; } } // arithmetic functions IntRep* add(const IntRep* x, int negatex, const IntRep* y, int negatey, IntRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; int ysgn = (negatey && yl != 0) ? !y->sgn : y->sgn; int xrsame = x == r; int yrsame = y == r; if (yl == 0) r = Ialloc(r, x->s, xl, xsgn, xl); else if (xl == 0) r = Ialloc(r, y->s, yl, ysgn, yl); else if (xsgn == ysgn) { if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 1)); else r = Icalloc(r, calc_len(xl, yl, 1)); r->sgn = xsgn; unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = (yrsame)? r->s : y->s; topb = &(bs[yl]); } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = (yrsame)? r->s : y->s; topa = &(as[yl]); } unsigned long sum = 0; while (bs < topb) { sum += (unsigned long)(*as++) + (unsigned long)(*bs++); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && as < topa) { sum += (unsigned long)(*as++); *rs++ = extract(sum); sum = down(sum); } if (sum != 0) *rs = extract(sum); else if (rs != as) while (as < topa) *rs++ = *as++; } else { int comp = ucompare(x, y); if (comp == 0) r = Icopy_zero(r); else { if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (comp > 0) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = (yrsame)? r->s : y->s; topb = &(bs[yl]); r->sgn = xsgn; } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = (yrsame)? r->s : y->s; topa = &(as[yl]); r->sgn = ysgn; } unsigned long hi = 1; while (bs < topb) { hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); *rs++ = extract(hi); hi = down(hi); } while (hi == 0 && as < topa) { hi = (unsigned long)(*as++) + I_MAXNUM; *rs++ = extract(hi); hi = down(hi); } if (rs != as) while (as < topa) *rs++ = *as++; } } Icheck(r); return r; } IntRep* add(const IntRep* x, int negatex, long y, IntRep* r) { nonnil(x); int xl = x->len; int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; int xrsame = x == r; int ysgn = (y >= 0); unsigned long uy = (ysgn)? y : -y; if (y == 0) r = Ialloc(r, x->s, xl, xsgn, xl); else if (xl == 0) r = Icopy_long(r, y); else if (xsgn == ysgn) { if (xrsame) r = Iresize(r, calc_len(xl, SHORT_PER_LONG, 1)); else r = Icalloc(r, calc_len(xl, SHORT_PER_LONG, 1)); r->sgn = xsgn; unsigned short* rs = r->s; const unsigned short* as = (xrsame)? r->s : x->s; const unsigned short* topa = &(as[xl]); unsigned long sum = 0; while (as < topa && uy != 0) { unsigned long u = extract(uy); uy = down(uy); sum += (unsigned long)(*as++) + u; *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && as < topa) { sum += (unsigned long)(*as++); *rs++ = extract(sum); sum = down(sum); } if (sum != 0) *rs = extract(sum); else if (rs != as) while (as < topa) *rs++ = *as++; } else { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, tmp, yl); if (comp == 0) r = Icopy_zero(r); else { if (xrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (comp > 0) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = tmp; topb = &(bs[yl]); r->sgn = xsgn; } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = tmp; topa = &(as[yl]); r->sgn = ysgn; } unsigned long hi = 1; while (bs < topb) { hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); *rs++ = extract(hi); hi = down(hi); } while (hi == 0 && as < topa) { hi = (unsigned long)(*as++) + I_MAXNUM; *rs++ = extract(hi); hi = down(hi); } if (rs != as) while (as < topa) *rs++ = *as++; } } Icheck(r); return r; } IntRep* multiply(const IntRep* x, const IntRep* y, IntRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int rl = xl + yl; int rsgn = x->sgn == y->sgn; int xrsame = x == r; int yrsame = y == r; int xysame = x == y; if (xl == 0 || yl == 0) r = Icopy_zero(r); else if (xl == 1 && x->s[0] == 1) r = Icopy(r, y); else if (yl == 1 && y->s[0] == 1) r = Icopy(r, x); else if (!(xysame && xrsame)) { if (xrsame || yrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); // use best inner/outer loop params given constraints unsigned short* currentr; const unsigned short* bota; const unsigned short* as; const unsigned short* botb; const unsigned short* topb; if (xrsame) { currentr = &(rs[xl-1]); bota = rs; as = currentr; botb = y->s; topb = &(botb[yl]); } else if (yrsame) { currentr = &(rs[yl-1]); bota = rs; as = currentr; botb = x->s; topb = &(botb[xl]); } else if (xl <= yl) { currentr = &(rs[xl-1]); bota = x->s; as = &(bota[xl-1]); botb = y->s; topb = &(botb[yl]); } else { currentr = &(rs[yl-1]); bota = y->s; as = &(bota[yl-1]); botb = x->s; topb = &(botb[xl]); } while (as >= bota) { unsigned long ai = (unsigned long)(*as--); unsigned short* rs = currentr--; *rs = 0; if (ai != 0) { unsigned long sum = 0; const unsigned short* bs = botb; while (bs < topb) { sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && rs < topr) { sum += (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } } } } else // x, y, and r same; compute over diagonals { r = Iresize(r, rl); unsigned short* botr = r->s; unsigned short* topr = &(botr[rl]); unsigned short* rs = &(botr[rl - 2]); const unsigned short* bota = (xrsame)? botr : x->s; const unsigned short* loa = &(bota[xl - 1]); const unsigned short* hia = loa; for (; rs >= botr; --rs) { const unsigned short* h = hia; const unsigned short* l = loa; unsigned long prod = (unsigned long)(*h) * (unsigned long)(*l); *rs = 0; for(;;) { unsigned short* rt = rs; unsigned long sum = prod + (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); while (sum != 0 && rt < topr) { sum += (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); } if (h > l) { rt = rs; sum = prod + (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); while (sum != 0 && rt < topr) { sum += (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); } if (--h >= ++l) prod = (unsigned long)(*h) * (unsigned long)(*l); else break; } else break; } if (loa > bota) --loa; else --hia; } } r->sgn = rsgn; Icheck(r); return r; } IntRep* multiply(const IntRep* x, long y, IntRep* r) { nonnil(x); int xl = x->len; if (xl == 0 || y == 0) r = Icopy_zero(r); else if (y == 1) r = Icopy(r, x); else { int ysgn = y >= 0; int rsgn = x->sgn == ysgn; unsigned long uy = (ysgn)? y : -y; unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } int rl = xl + yl; int xrsame = x == r; if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); unsigned short* currentr; const unsigned short* bota; const unsigned short* as; const unsigned short* botb; const unsigned short* topb; if (xrsame) { currentr = &(rs[xl-1]); bota = rs; as = currentr; botb = tmp; topb = &(botb[yl]); } else if (xl <= yl) { currentr = &(rs[xl-1]); bota = x->s; as = &(bota[xl-1]); botb = tmp; topb = &(botb[yl]); } else { currentr = &(rs[yl-1]); bota = tmp; as = &(bota[yl-1]); botb = x->s; topb = &(botb[xl]); } while (as >= bota) { unsigned long ai = (unsigned long)(*as--); unsigned short* rs = currentr--; *rs = 0; if (ai != 0) { unsigned long sum = 0; const unsigned short* bs = botb; while (bs < topb) { sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && rs < topr) { sum += (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } } } r->sgn = rsgn; } Icheck(r); return r; } // main division routine static void do_divide(unsigned short* rs, const unsigned short* ys, int yl, unsigned short* qs, int ql) { const unsigned short* topy = &(ys[yl]); unsigned short d1 = ys[yl - 1]; unsigned short d2 = ys[yl - 2]; int l = ql - 1; int i = l + yl; for (; l >= 0; --l, --i) { unsigned short qhat; // guess q if (d1 == rs[i]) qhat = I_MAXNUM; else { unsigned long lr = up((unsigned long)rs[i]) | rs[i-1]; qhat = lr / d1; } for(;;) // adjust q, use docmp to avoid overflow problems { unsigned short ts[3]; unsigned long prod = (unsigned long)d2 * (unsigned long)qhat; ts[0] = extract(prod); prod = down(prod) + (unsigned long)d1 * (unsigned long)qhat; ts[1] = extract(prod); ts[2] = extract(down(prod)); if (docmp(ts, &(rs[i-2]), 3) > 0) --qhat; else break; }; // multiply & subtract const unsigned short* yt = ys; unsigned short* rt = &(rs[l]); unsigned long prod = 0; unsigned long hi = 1; while (yt < topy) { prod = (unsigned long)qhat * (unsigned long)(*yt++) + down(prod); hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(extract(prod)); *rt++ = extract(hi); hi = down(hi); } hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(down(prod)); *rt = extract(hi); hi = down(hi); // off-by-one, add back if (hi == 0) { --qhat; yt = ys; rt = &(rs[l]); hi = 0; while (yt < topy) { hi = (unsigned long)(*rt) + (unsigned long)(*yt++) + down(hi); *rt++ = extract(hi); } *rt = 0; } if (qs != 0) qs[l] = qhat; } } // divide by single digit, return remainder // if q != 0, then keep the result in q, else just compute rem static int unscale(const unsigned short* x, int xl, unsigned short y, unsigned short* q) { if (xl == 0 || y == 1) return 0; else if (q != 0) { unsigned short* botq = q; unsigned short* qs = &(botq[xl - 1]); const unsigned short* xs = &(x[xl - 1]); unsigned long rem = 0; while (qs >= botq) { rem = up(rem) | *xs--; unsigned long u = rem / y; *qs-- = extract(u); rem -= u * y; } int r = extract(rem); return r; } else // same loop, a bit faster if just need rem { const unsigned short* botx = x; const unsigned short* xs = &(botx[xl - 1]); unsigned long rem = 0; while (xs >= botx) { rem = up(rem) | *xs--; unsigned long u = rem / y; rem -= u * y; } int r = extract(rem); return r; } } IntRep* div(const IntRep* x, const IntRep* y, IntRep* q) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); int comp = ucompare(x, y); int xsgn = x->sgn; int ysgn = y->sgn; int samesign = xsgn == ysgn; if (comp < 0) q = Icopy_zero(q); else if (comp == 0) q = Icopy_one(q, samesign); else if (yl == 1) { q = Icopy(q, x); unscale(q->s, q->len, y->s[0], q->s); } else { IntRep* yy = 0; IntRep* r = 0; unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == q) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntRep*)y; r = Icopy(r, x); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, yy->s, yl, q->s, ql); if (yy != y) delete yy; delete r; } q->sgn = samesign; Icheck(q); return q; } IntRep* div(const IntRep* x, long y, IntRep* q) { nonnil(x); int xl = x->len; if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; int samesign = xsgn == ysgn; if (comp < 0) q = Icopy_zero(q); else if (comp == 0) { q = Icopy_one(q, samesign); } else if (yl == 1) { q = Icopy(q, x); unscale(q->s, q->len, ys[0], q->s); } else { IntRep* r = 0; unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icopy(r, x); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); delete r; } q->sgn = samesign; Icheck(q); return q; } void divide(const Integer& Ix, long y, Integer& Iq, long& rem) { const IntRep* x = Ix.rep; nonnil(x); IntRep* q = Iq.rep; int xl = x->len; if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; int samesign = xsgn == ysgn; if (comp < 0) { rem = Itolong(x); q = Icopy_zero(q); } else if (comp == 0) { q = Icopy_one(q, samesign); rem = 0; } else if (yl == 1) { q = Icopy(q, x); rem = unscale(q->s, q->len, ys[0], q->s); } else { IntRep* r = 0; unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icopy(r, x); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } Icheck(r); rem = Itolong(r); delete r; } rem = abs(rem); if (xsgn == I_NEGATIVE) rem = -rem; q->sgn = samesign; Icheck(q); Iq.rep = q; } void divide(const Integer& Ix, const Integer& Iy, Integer& Iq, Integer& Ir) { const IntRep* x = Ix.rep; nonnil(x); const IntRep* y = Iy.rep; nonnil(y); IntRep* q = Iq.rep; IntRep* r = Ir.rep; int xl = x->len; int yl = y->len; if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); int comp = ucompare(x, y); int xsgn = x->sgn; int ysgn = y->sgn; int samesign = xsgn == ysgn; if (comp < 0) { q = Icopy_zero(q); r = Icopy(r, x); } else if (comp == 0) { q = Icopy_one(q, samesign); r = Icopy_zero(r); } else if (yl == 1) { q = Icopy(q, x); int rem = unscale(q->s, q->len, y->s[0], q->s); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntRep* yy = 0; unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == q || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntRep*)y; r = Icopy(r, x); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, yy->s, yl, q->s, ql); if (yy != y) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } q->sgn = samesign; Icheck(q); Iq.rep = q; Icheck(r); Ir.rep = r; } IntRep* mod(const IntRep* x, const IntRep* y, IntRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); int comp = ucompare(x, y); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, y->s[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntRep* yy = 0; unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntRep*)y; r = Icopy(r, x); } do_divide(r->s, yy->s, yl, 0, xl - yl + 1); if (yy != y) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r; } IntRep* mod(const IntRep* x, long y, IntRep* r) { nonnil(x); int xl = x->len; if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, ys[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icopy(r, x); } do_divide(r->s, ys, yl, 0, xl - yl + 1); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r; } IntRep* lshift(const IntRep* x, long y, IntRep* r) { nonnil(x); int xl = x->len; if (xl == 0 || y == 0) { r = Icopy(r, x); return r; } int xrsame = x == r; int rsgn = x->sgn; long ay = (y < 0)? -y : y; int bw = ay / I_SHIFT; int sw = ay % I_SHIFT; if (y > 0) { int rl = bw + xl + 1; if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* botr = r->s; unsigned short* rs = &(botr[rl - 1]); const unsigned short* botx = (xrsame)? botr : x->s; const unsigned short* xs = &(botx[xl - 1]); unsigned long a = 0; while (xs >= botx) { a = up(a) | ((unsigned long)(*xs--) << sw); *rs-- = extract(down(a)); } *rs-- = extract(a); while (rs >= botr) *rs-- = 0; } else { int rl = xl - bw; if (rl < 0) r = Icopy_zero(r); else { if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); int rw = I_SHIFT - sw; unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); const unsigned short* botx = (xrsame)? rs : x->s; const unsigned short* xs = &(botx[bw]); const unsigned short* topx = &(botx[xl]); unsigned long a = (unsigned long)(*xs++) >> sw; while (xs < topx) { a |= (unsigned long)(*xs++) << rw; *rs++ = extract(a); a = down(a); } *rs++ = extract(a); if (xrsame) topr = (unsigned short*)topx; while (rs < topr) *rs++ = 0; } } r->sgn = rsgn; Icheck(r); return r; } IntRep* lshift(const IntRep* x, const IntRep* yy, int negatey, IntRep* r) { long y = Itolong(yy); if (negatey) y = -y; return lshift(x, y, r); } IntRep* bitop(const IntRep* x, const IntRep* y, IntRep* r, char op) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int xsgn = x->sgn; int xrsame = x == r; int yrsame = y == r; if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = (yrsame)? rs : y->s; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = (yrsame)? rs : y->s; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r; } IntRep* bitop(const IntRep* x, long y, IntRep* r, char op) { nonnil(x); unsigned short tmp[SHORT_PER_LONG]; unsigned long u; int newsgn; if (newsgn = (y >= 0)) u = y; else u = -y; int l = 0; while (u != 0) { tmp[l++] = extract(u); u = down(u); } int xl = x->len; int yl = l; int xsgn = x->sgn; int xrsame = x == r; if (xrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = tmp; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = tmp; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r; } IntRep* compl(const IntRep* src, IntRep* r) { nonnil(src); r = Icopy(r, src); unsigned short* s = r->s; unsigned short* top = &(s[r->len - 1]); while (s < top) { unsigned short cmp = ~(*s); *s++ = cmp; } unsigned short a = *s; unsigned short b = 0; while (a != 0) { b <<= 1; if (!(a & 1)) b |= 1; a >>= 1; } *s = b; Icheck(r); return r; } void setbit(Integer& x, long b) { if (b >= 0) { int bw = (unsigned long)b / I_SHIFT; int sw = (unsigned long)b % I_SHIFT; if (x.rep == 0) x.rep = Icalloc(0, bw + 1); else if (x.rep->len < bw) { int xl = x.rep->len; x.rep = Iresize(x.rep, calc_len(xl, bw+1, 0)); } x.rep->s[bw] |= (1 << sw); Icheck(x.rep); } } void clearbit(Integer& x, long b) { if (b >= 0) { int bw = (unsigned long)b / I_SHIFT; int sw = (unsigned long)b % I_SHIFT; if (x.rep == 0) x.rep = Icalloc(0, bw + 1); else if (x.rep->len < bw) { int xl = x.rep->len; x.rep = Iresize(x.rep, calc_len(xl, bw+1, 0)); } x.rep->s[bw] &= ~(1 << sw); Icheck(x.rep); } } int testbit(const Integer& x, long b) { if (x.rep != 0 && b >= 0) { int bw = (unsigned long)b / I_SHIFT; int sw = (unsigned long)b % I_SHIFT; return (bw < x.rep->len && (x.rep->s[bw] & (1 << sw)) != 0); } else return 0; } // A version of knuth's algorithm B / ex. 4.5.3.34 // A better version that doesn't bother shifting all of `t' forthcoming IntRep* gcd(const IntRep* x, const IntRep* y) { nonnil(x); nonnil(y); int ul = x->len; int vl = y->len; if (vl == 0) return Ialloc(0, x->s, ul, I_POSITIVE, ul); else if (ul == 0) return Ialloc(0, y->s, vl, I_POSITIVE, vl); IntRep* u = Ialloc(0, x->s, ul, I_POSITIVE, ul); IntRep* v = Ialloc(0, y->s, vl, I_POSITIVE, vl); // find shift so that both not even long k = 0; int l = (ul <= vl)? ul : vl; int cont = 1; for (int i = 0; i < l && cont; ++i) { unsigned long a = (i < ul)? u->s[i] : 0; unsigned long b = (i < vl)? v->s[i] : 0; for (int j = 0; j < I_SHIFT; ++j) { if ((a | b) & 1) { cont = 0; break; } else { ++k; a >>= 1; b >>= 1; } } } if (k != 0) { u = lshift(u, -k, u); v = lshift(v, -k, v); } IntRep* t; if (u->s[0] & 01) t = Ialloc(0, v->s, v->len, !v->sgn, v->len); else t = Ialloc(0, u->s, u->len, u->sgn, u->len); while (t->len != 0) { long s = 0; // shift t until odd cont = 1; int tl = t->len; for (i = 0; i < tl && cont; ++i) { unsigned long a = t->s[i]; for (int j = 0; j < I_SHIFT; ++j) { if (a & 1) { cont = 0; break; } else { ++s; a >>= 1; } } } if (s != 0) t = lshift(t, -s, t); if (t->sgn == I_POSITIVE) { u = Icopy(u, t); t = add(t, 0, v, 1, t); } else { v = Ialloc(v, t->s, t->len, !t->sgn, t->len); t = add(t, 0, u, 0, t); } } delete t; delete v; if (k != 0) u = lshift(u, k, u); return u; } Integer lcm(const Integer& x, const Integer& y) return r { if (!x.initialized() || !y.initialized()) x.error("operation on uninitialized Integer"); Integer g; if (sign(x) == 0 || sign(y) == 0) g = 1; else g = gcd(x, y); div(x, g, r); mul(r, y, r); } long lg(const IntRep* x) { nonnil(x); int xl = x->len; if (xl == 0) return 0; long l = (xl - 1) * I_SHIFT - 1; unsigned short a = x->s[xl-1]; while (a != 0) { a = a >> 1; ++l; } return l; } IntRep* power(const IntRep* x, long y, IntRep* r) { nonnil(x); int sgn; if (x->sgn == I_POSITIVE || (!(y & 1))) sgn = I_POSITIVE; else sgn = I_NEGATIVE; int xl = x->len; if (y == 0 || (xl == 1 && x->s[0] == 1)) r = Icopy_one(r, sgn); else if (xl == 0 || y < 0) r = Icopy_zero(r); else if (y == 1 || y == -1) r = Icopy(r, x); else { int maxsize = ((lg(x) + 1) * y) / I_SHIFT + 2; // pre-allocate space IntRep* b = Ialloc(0, x->s, xl, I_POSITIVE, maxsize); b->len = xl; r = Icalloc(r, maxsize); r = Icopy_one(r, I_POSITIVE); for(;;) { if (y & 1) r = multiply(r, b, r); if ((y >>= 1) == 0) break; else b = multiply(b, b, b); } delete b; } r->sgn = sgn; Icheck(r); return r; } IntRep* abs(const IntRep* src, IntRep* dest) { nonnil(src); if (src != dest) dest = Icopy(dest, src); dest->sgn = I_POSITIVE; return dest; } IntRep* negate(const IntRep* src, IntRep* dest) { nonnil(src); if (src != dest) dest = Icopy(dest, src); if (dest->len != 0) dest->sgn = !dest->sgn; return dest; } Integer sqrt(const Integer& x) return r(x) { int s = sign(x); if (s < 0) x.error("Attempted square root of negative Integer"); if (s != 0) { r >>= (lg(x) / 2); // get close Integer q; div(x, r, q); while (q < r) { r += q; r >>= 1; div(x, r, q); } } return; } IntRep* atoIntRep(const char* s, int base) { int sl = strlen(s); IntRep* r = Icalloc(0, sl * (lg(base) + 1) / I_SHIFT + 1); if (s != 0) { char sgn; while (isspace(*s)) ++s; if (*s == '-') { sgn = I_NEGATIVE; s++; } else if (*s == '+') { sgn = I_POSITIVE; s++; } else sgn = I_POSITIVE; for (;;) { long digit; if (*s >= '0' && *s <= '9') digit = *s - '0'; else if (*s >= 'a' && *s <= 'z') digit = *s - 'a' + 10; else if (*s >= 'A' && *s <= 'Z') digit = *s - 'A' + 10; else break; if (digit >= base) break; r = multiply(r, base, r); r = add(r, 0, digit, r); r->sgn = sgn; ++s; } } return r; } extern AllocRing _libgxx_fmtq; char* Itoa(const IntRep* x, int base, int width) { int wrksiz = (x->len + 1) * I_SHIFT / lg(base) + 2 + width; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* e = fmtbase + wrksiz - 1; char* s = e; *--s = 0; if (x->len == 0) *--s = '0'; else { IntRep* z = Icopy(0, x); // split division by base into two parts: // first divide by biggest power of base that fits in an unsigned short, // then use straight signed div/mods from there. // find power int bpower = 1; unsigned short b = base; unsigned short maxb = I_MAXNUM / base; while (b < maxb) { b *= base; ++bpower; } for(;;) { int rem = unscale(z->s, z->len, b, z->s); Icheck(z); if (z->len == 0) { while (rem != 0) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } delete z; break; } else { for (int i = 0; i < bpower; ++i) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } } } if (x->sgn == I_NEGATIVE) *--s = '-'; int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } char* dec(const Integer& x, int width) { return Itoa(x, 10, width); } char* oct(const Integer& x, int width) { return Itoa(x, 8, width); } char* hex(const Integer& x, int width) { return Itoa(x, 16, width); } istream& operator >> (istream& s, Integer& y) { if (!s.readable()) { s.set(_bad); return s; } int got_one = 0; char sgn = 0; char ch; y.rep = Icopy_zero(y.rep); s >> WS; if (!s.good()) { s.set(_bad); return s; } while (s.get(ch)) { if (ch == '-') { if (sgn == 0) sgn = '-'; else break; } else if (ch >= '0' && ch <= '9') { long digit = ch - '0'; y *= 10; y += digit; got_one = 1; } else break; } if (s.good()) s.unget(ch); if (!got_one) s.set(_bad); if (sgn == '-') y.negate(); return s; } int Integer::OK() const { int v = rep != 0; // have a rep int l = rep->len; int s = rep->sgn; v &= l <= rep->sz; // length with bounds v &= s == 0 || s == 1; // legal sign Icheck(rep); // and correctly adjusted v &= rep->len == l; v &= rep->sgn == s; if (!v) error("invariant failure"); return v; } volatile void Integer::error(const char* msg) const { (*lib_error_handler)("Integer", msg); } if (sgn == '-') y.negate(); return s; } int Integer::OK() const { int v = rep != 0; // have a rep int l = rep->len; int s = rep->sgn; v &= l <= rep->sz; // length with bounds v &= s == 0 || s == 1; // legal sign Icheck(rep); // and correctly adjusted v &= rep->len == l; v &= rep->sgn == s; if (!v) error("invariant failure"); return v; } volatile void Integer::error(const char* msg) const { (*lib_error_handler)("Integer",libg++/src/MLCG.cc 644 473 0 3572 4677700047 6770 #include "MLCG.h" // // SEED_TABLE_SIZE must be a power of 2 // #define SEED_TABLE_SIZE 32 static long seedTable[SEED_TABLE_SIZE] = { 0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b, 0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf, 0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706, 0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10, 0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a, 0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32, 0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f, 0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf }; MLCG::MLCG(long seed1, long seed2) { initialSeedOne = seed1; initialSeedTwo = seed2; reset(); } void MLCG::reset() { long seed1 = initialSeedOne; long seed2 = initialSeedTwo; // // Most people pick stupid seed numbers that do not have enough // bits. In this case, if they pick a small seed number, we // map that to a specific seed. // if (seed1 < 0) { seed1 = (seed1 + 2147483561); seed1 = (seed1 < 0) ? -seed1 : seed1; } if (seed2 < 0) { seed2 = (seed2 + 2147483561); seed2 = (seed2 < 0) ? -seed2 : seed2; } if (seed1 > -1 && seed1 < SEED_TABLE_SIZE) { seedOne = seedTable[seed1]; } else { seedOne = seed1 ^ seedTable[seed1 & (SEED_TABLE_SIZE-1)]; } if (seed2 > -1 && seed2 < SEED_TABLE_SIZE) { seedTwo = seedTable[seed2]; } else { seedTwo = seed2 ^ seedTable[ seed2 & (SEED_TABLE_SIZE-1) ]; } seedOne = (seedOne % 2147483561) + 1; seedTwo = (seedTwo % 2147483397) + 1; } unsigned long MLCG::asLong() { long k = seedOne % 53668; seedOne = 40014 * (seedOne-k * 53668) - k * 12211; if (seedOne < 0) { seedOne += 2147483563; } k = seedTwo % 52774; seedTwo = 40692 * (seedTwo - k * 52774) - k * 3791; if (seedTwo < 0) { seedTwo += 2147483399; } long z = seedOne - seedTwo; if (z < 1) { z += 2147483562; } return( (unsigned long) z); } 1) ]; } seedOne = (seedOne % 2147483561) + 1; seedTwo = (seedTwo % 2147483397) + 1; } unsigned long MLCG::asLong() { libg++/src/Obstack.cc 644 473 0 5775 4677700047 7643 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include Obstack::Obstack(int size, int alignment) { alignmentmask = alignment - 1; chunksize = size; chunk = 0; nextfree = objectbase = 0; chunklimit = 0; } void Obstack::_free(void* obj) { _obstack_chunk* lp; _obstack_chunk* plp; lp = chunk; while (lp != 0 && ((void*)lp > obj || (void*)(lp)->limit < obj)) { plp = lp -> prev; delete(lp); lp = plp; } if (lp) { objectbase = nextfree = (char *)(obj); chunklimit = lp->limit; chunk = lp; } else if (obj != 0) (*lib_error_handler)("Obstack", "deletion of nonexistent obj"); } void Obstack::newchunk(int size) { _obstack_chunk* old_chunk = chunk; _obstack_chunk* new_chunk; long new_size; int obj_size = nextfree - objectbase; new_size = (obj_size + size) << 1; if (new_size < chunksize) new_size = chunksize; new_chunk = chunk = (_obstack_chunk*)(new char[new_size]); new_chunk->prev = old_chunk; new_chunk->limit = chunklimit = (char *) new_chunk + new_size; bcopy((void*)objectbase, (void*)new_chunk->contents, obj_size); objectbase = new_chunk->contents; nextfree = objectbase + obj_size; } void* Obstack::finish() { void* value = (void*) objectbase; nextfree = (char*)((int)(nextfree + alignmentmask) & ~(alignmentmask)); if (nextfree - (char*)chunk > chunklimit - (char*)chunk) nextfree = chunklimit; objectbase = nextfree; return value; } int Obstack::contains(void* obj) // true if obj somewhere in Obstack { for (_obstack_chunk* ch = chunk; ch != 0 && (obj < (void*)ch || obj >= (void*)(ch->limit)); ch = ch->prev); return ch != 0; } int Obstack::OK() { int v = chunksize > 0; // valid size v &= alignmentmask != 0; // and alignment v &= chunk != 0; v &= objectbase >= chunk->contents; v &= nextfree >= objectbase; v &= nextfree <= chunklimit; v &= chunklimit == chunk->limit; _obstack_chunk* p = chunk; // allow lots of chances to find bottom! long x = MAXLONG; while (p != 0 && x != 0) { --x; p = p->prev; } v &= x > 0; if (!v) (*lib_error_handler)("Obstack", "invariant failure"); return v; } libg++/src/PlotFile.cc 644 473 0 7461 4677700047 7765 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include /* PlotFile implementation module */ PlotFile:: PlotFile() {} PlotFile::~PlotFile() {} PlotFile::PlotFile(const char* filename, const io_mode m, const access_mode a) :(filename, m, a) {} PlotFile::PlotFile(const char* filename, const char* m) :(filename, m) {} PlotFile::PlotFile(int filedesc, const io_mode m = io_writeonly) :(filedesc, m) {} PlotFile::PlotFile(FILE* fileptr) :(fileptr) {} PlotFile::operator void*() { return (state & (_bad|_fail))? 0 : this ; } PlotFile& PlotFile::open(const char* filename, const io_mode m, const access_mode a) { File::open(filename, m, a); return *this; } PlotFile& PlotFile::open(const char* filename, const char* m) { File::open(filename, m); return *this; } PlotFile& PlotFile::open(const int filedesc, const io_mode m) { File::open(filedesc, m); return *this; } PlotFile& PlotFile::open(FILE* fileptr) { File::open(fileptr); return *this; } PlotFile& PlotFile::setbuf(const int buffer_kind) { File::setbuf(buffer_kind); return *this; } PlotFile& PlotFile::setbuf(const int size, char* buf) { File::setbuf(size, buf); return *this; } PlotFile& PlotFile:: cmd(char c) { File::put(c); return *this; } PlotFile& PlotFile:: operator<<(const int x) { #if defined(convex) File::put((char)(x>>8)); File::put((char)(x&0377)); #else File::put((char)(x&0377)); File::put((char)(x>>8)); #endif return *this; } PlotFile& PlotFile:: operator<<(const char *s) { File::put(s); return *this; } PlotFile& PlotFile:: arc(const int xi, const int yi, const int x0, const int y0, const int x1, const int y1) { return cmd('a') << xi << yi << x0 << y0 << x1 << y1; } PlotFile& PlotFile:: box(const int x0, const int y0, const int x1, const int y1) { line(x0, y0, x0, y1); line(x0, y1, x1, y1); line(x1, y1, x1, y0); return line(x1, y0, x0, y0); } PlotFile& PlotFile:: circle(const int x, const int y, const int r) { return cmd('c') << x << y << r; } PlotFile& PlotFile:: cont(const int xi, const int yi) { return cmd('n') << xi << yi; } PlotFile& PlotFile:: dot(const int xi, const int yi, const int dx, int n, const int* pat) { cmd('d') << xi << yi << dx << n; while (n-- > 0) *this << *pat++; return *this; } PlotFile& PlotFile:: erase() { return cmd('e'); } PlotFile& PlotFile:: label(const char* s) { return cmd('t') << s << "\n"; } PlotFile& PlotFile:: line(const int x0, const int y0, const int x1, const int y1) { return cmd('l') << x0 << y0 << x1 << y1; } PlotFile& PlotFile:: linemod(const char* s) { return cmd('f') << s << "\n"; } PlotFile& PlotFile:: move(const int xi, const int yi) { return cmd('m') << xi << yi; } PlotFile& PlotFile:: point(const int xi, const int yi) { return cmd('p') << xi << yi; } PlotFile& PlotFile:: space(const int x0, const int y0, const int x1, const int y1) { return cmd('s') << x0 << y0 << x1 << y1; } t int x0, const int y0, const int x1, const int y1) { return cmd('l') << x0 << y0 << x1 << y1; } PlotFile& PlotFile:: linemod(const char* s) { return cmd('f') << s << "\n"; } PlotFile& PlotFillibg++/src/RNG.cc 644 473 0 3736 4677700047 6676 #include #include #include #include // // The scale constant is 2^-31. It is used to scale a 31 bit // long to a double. // //static const double randomDoubleScaleConstant = 4.656612873077392578125e-10; //static const float randomFloatScaleConstant = 4.656612873077392578125e-10; static char initialized = 0; RNG::RNG() { if (!initialized) { assert (sizeof(double) == 2 * sizeof(unsigned long)); // // The following is a hack that I attribute to // Andres Nowatzyk at CMU. The intent of the loop // is to form the smallest number 0 <= x < 1.0, // which is then used as a mask for two longwords. // this gives us a fast way way to produce double // precision numbers from longwords. // // I know that this works for IEEE and VAX floating // point representations. // // A further complication is that gnu C will blow // the following loop, unless compiled with -ffloat-store, // because it uses extended representations for some of // of the comparisons. Thus, we have the following hack. // If we could specify #pragma optimize, we wouldn't need this. // PrivateRNGDoubleType t; PrivateRNGSingleType s; #if _IEEE == 1 t.d = 1.5; if ( t.u[1] == 0 ) { // sun word order? t.u[0] = 0x3fffffff; t.u[1] = 0xffffffff; } else { t.u[0] = 0xffffffff; // encore word order? t.u[1] = 0x3fffffff; } s.u = 0x3fffffff; #else double x = 1.0; double y = 0.5; do { // find largest fp-number < 2.0 t.d = x; x += y; y *= 0.5; } while (x != t.d && x < 2.0); float xx = 1.0; float yy = 0.5; do { // find largest fp-number < 2.0 s.s = xx; xx += yy; yy *= 0.5; } while (xx != s.s && xx < 2.0); #endif // set doubleMantissa to 1 for each doubleMantissa bit doubleMantissa.d = 1.0; doubleMantissa.u[0] ^= t.u[0]; doubleMantissa.u[1] ^= t.u[1]; // set singleMantissa to 1 for each singleMantissa bit singleMantissa.s = 1.0; singleMantissa.u ^= s.u; initialized = 1; } } = x; x += y; y *= 0.5; libg++/src/SFile.cc 644 473 0 2424 4677700047 7243 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include SFile::SFile() {} SFile::~SFile() {} SFile::SFile(const char* filename, int size, io_mode m, access_mode a) : (filename, m, a) { sz = size; } SFile::SFile(const char* filename, int size, const char* m) : (filename, m) { sz = size; } SFile::SFile(int filedesc, int size, io_mode m) : (filedesc, m) { sz = size; } SFile::SFile(FILE* fileptr, int size) : (fileptr) { sz = size; } her things, the copyright notice and this notice must be preserved on all copies. */ #include SFile::SFile() {} SFile::~SFile() {} SFile::SFile(const char* filename, int size, io_mode m, access_mode a) : (filename, m, a) libg++/src/Sample.cc 644 473 0 11716 4677700050 7500 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // error handling void default_SampleStatistic_error_handler(const char* msg) { cerr << "Fatal SampleStatistic error. " << msg << "\n"; exit(1); } one_arg_error_handler_t SampleStatistic_error_handler = default_SampleStatistic_error_handler; one_arg_error_handler_t set_SampleStatistic_error_handler(one_arg_error_handler_t f) { one_arg_error_handler_t old = SampleStatistic_error_handler; SampleStatistic_error_handler = f; return old; } void SampleStatistic::error(const char* msg) { (*SampleStatistic_error_handler)(msg); } // t-distribution: given p-value and degrees of freedom, return t-value // adapted from Peizer & Pratt JASA, vol63, p1416 double tval(double p, int df) { double t; int positive = p >= 0.5; p = (positive)? 1.0 - p : p; if (p <= 0.0 || df == 0) t = HUGE; else if (p == 0.5) t = 0.0; else if (df == 1) t = 1.0 / tan((p + p) * 1.57079633); else if (df == 2) t = sqrt(1.0 / ((p + p) * (1.0 - p)) - 2.0); else { double ddf = df; double a = sqrt(log(1.0 / (p * p))); double aa = a * a; a = a - ((2.515517 + (0.802853 * a) + (0.010328 * aa)) / (1.0 + (1.432788 * a) + (0.189269 * aa) + (0.001308 * aa * a))); t = ddf - 0.666666667 + 1.0 / (10.0 * ddf); t = sqrt(ddf * (exp(a * a * (ddf - 0.833333333) / (t * t)) - 1.0)); } return (positive)? t : -t; } void SampleStatistic::reset() { n = 0; x = x2 = 0.0; maxValue = -HUGE; minValue = HUGE; } void SampleStatistic::operator+=(double value) { n += 1; x += value; x2 += (value * value); if ( minValue > value) minValue = value; if ( maxValue < value) maxValue = value; } double SampleStatistic::mean() { if ( n > 0) { return (x / n); } else { return ( 0.0 ); } } double SampleStatistic::var() { if ( n > 1) { return(( x2 - ((x * x) / n)) / ( n - 1)); } else { return ( 0.0 ); } } double SampleStatistic::stdDev() { if ( n <= 0 || this -> var() <= 0) { return(0); } else { return( (double) sqrt( var() ) ); } } double SampleStatistic::confidence(int interval) { double t = tval(double(100 + interval) * 0.005, n); if (t == HUGE) return t; else return (t * stdDev()) / sqrt(double(n)); } double SampleStatistic::confidence(double p_value) { double t = tval((1.0 + p_value) * 0.5, n); if (t == HUGE) return t; else return (t * stdDev()) / sqrt(double(n)); } #include const int SampleHistogramMinimum = -2; const int SampleHistogramMaximum = -1; SampleHistogram::SampleHistogram(double low, double high, double width) { if (high < low) { double t = high; high = low; low = t; } if (width == -1) { width = (high - low) / 10; } howManyBuckets = int((high - low) / width) + 2; bucketCount = new int[howManyBuckets]; bucketLimit = new double[howManyBuckets]; double lim = low; for (int i = 0; i < howManyBuckets; i++) { bucketCount[i] = 0; bucketLimit[i] = lim; lim += width; } bucketLimit[howManyBuckets-1] = HUGE; /* from math.h */ } SampleHistogram::~SampleHistogram() { if (howManyBuckets > 0) { delete bucketCount; delete bucketLimit; } } void SampleHistogram::operator+=(double value) { int i; for (i = 0; i < howManyBuckets; i++) { if (value < bucketLimit[i]) break; } bucketCount[i]++; this->SampleStatistic::operator+=(value); } int SampleHistogram::similarSamples(double d) { int i; for (i = 0; i < howManyBuckets; i++) { if (d < bucketLimit[i]) return(bucketCount[i]); } return(0); } void SampleHistogram::printBuckets(ostream& s) { for(int i = 0; i < howManyBuckets; i++) { if (bucketLimit[i] >= HUGE) { s << "< max : " << bucketCount[i] << "\n"; } else { s << "< " << bucketLimit[i] << " : " << bucketCount[i] << "\n"; } } } void SampleHistogram::reset() { this->SampleStatistic::reset(); if (howManyBuckets > 0) { for (register int i = 0; i < howManyBuckets; i++) { bucketCount[i] = 0; } } } tLimit[i]) return(bucketCount[i]); } returlibg++/src/String.cc 644 473 0 67146 4677700050 7535 /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* String class implementation */ #include #include #include #include #include // extern "C" { #include // } volatile void String::error(const char* msg) const { (void)((*lib_error_handler)("String", msg)); } // globals StrRep _nilStrRep = { 0, 1, { 0 } }; // nil strings point here String _nilString; // nil SubStrings point here /* the following inline fcts are specially designed to work in support of String classes, and are not meant as generic replacements for libc "str" functions. inline copy fcts - I like left-to-right from->to arguments. all versions assume that `to' argument is non-null These are worth doing inline, rather than through calls because, via procedural integration, adjacent copy calls can be smushed together by the optimizer. */ // copy n bytes inline static void ncopy(const char* from, char* to, int n) { if (from != to) while (--n >= 0) *to++ = *from++; } // copy n bytes, null-terminate inline static void ncopy0(const char* from, char* to, int n) { if (from != to) { while (--n >= 0) *to++ = *from++; *to = 0; } } // copy until null inline static void scopy(const char* from, char* to) { if (from != 0) while((*to++ = *from++) != 0); } // copy right-to-left inline static void revcopy(const char* from, char* to, short n) { if (from != 0) while (--n >= 0) *to-- = *from--; } inline static int slen(const char* t) // inline strlen { if (t == 0) return 0; else { const char* a = t; while (*a++ != 0); return a - 1 - t; } } // minimum & maximum representable rep size #define MAXStrRep_SIZE ((1 << (SHORTBITS - 1)) - 1) #define MINStrRep_SIZE 16 #ifndef MALLOC_MIN_OVERHEAD #define MALLOC_MIN_OVERHEAD 4 #endif // The basic allocation primitive: // Always round request to something close to a power of two. // This ensures a bit of padding, which often means that // concatenations don't have to realloc. Plus it tends to // be faster when lots of Strings are created and discarded, // since just about any version of malloc (op new()) will // be faster when it can reuse identically-sized chunks inline static StrRep* Snew(int newsiz) { unsigned int siz = sizeof(StrRep) + newsiz + MALLOC_MIN_OVERHEAD; unsigned int allocsiz = MINStrRep_SIZE; while (allocsiz < siz) allocsiz <<= 1; allocsiz -= MALLOC_MIN_OVERHEAD; if (allocsiz >= MAXStrRep_SIZE) (*lib_error_handler)("String", "Requested length out of range"); StrRep* rep = (StrRep *) new char[allocsiz]; rep->sz = allocsiz - sizeof(StrRep); return rep; } // Do-something-while-allocating routines. // We live with two ways to signify empty Sreps: either the // null pointer (0) or a pointer to the nilStrRep. // We always signify unknown source lengths (usually when fed a char*) // via len == -1, in which case it is computed. // allocate, copying src if nonull StrRep* Salloc(StrRep* old, const char* src, int srclen, int newlen) { if (old == &_nilStrRep) old = 0; if (srclen < 0) srclen = slen(src); if (newlen < srclen) newlen = srclen; StrRep* rep; if (old == 0 || newlen > old->sz) rep = Snew(newlen); else rep = old; rep->len = newlen; ncopy0(src, rep->s, srclen); if (old != rep && old != 0) delete old; return rep; } // reallocate: Given the initial allocation scheme, it will // generally be faster in the long run to get new space & copy // than to call realloc StrRep* Sresize(StrRep* old, int newlen) { if (old == &_nilStrRep) old = 0; StrRep* rep; if (old == 0) rep = Snew(newlen); else if (newlen > old->sz) { rep = Snew(newlen); ncopy0(old->s, rep->s, old->len); delete old; } else rep = old; rep->len = newlen; return rep; } // like allocate, but we know that src is a StrRep StrRep* Scopy(StrRep* old, StrRep* s) { if (old == &_nilStrRep) old = 0; if (s == &_nilStrRep) s = 0; if (old == s) return (old == 0)? &_nilStrRep : old; else if (s == 0) { old->s[0] = 0; old->len = 0; return old; } else { StrRep* rep; int newlen = s->len; if (old == 0 || newlen > old->sz) { if (old != 0) delete old; rep = Snew(newlen); } else rep = old; rep->len = newlen; ncopy0(s->s, rep->s, newlen); return rep; } } // allocate & concatenate StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen) { if (old == &_nilStrRep) old = 0; if (srclen < 0) srclen = slen(s); if (tlen < 0) tlen = slen(t); int newlen = srclen + tlen; StrRep* rep; if (old == 0 || newlen > old->sz || (t >= old->s && t < &(old->s[old->len]))) // beware of aliasing rep = Snew(newlen); else rep = old; rep->len = newlen; ncopy(s, rep->s, srclen); ncopy0(t, &(rep->s[srclen]), tlen); if (old != rep && old != 0) delete old; return rep; } // double-concatenate StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen, const char* u, int ulen) { if (old == &_nilStrRep) old = 0; if (srclen < 0) srclen = slen(s); if (tlen < 0) tlen = slen(t); if (ulen < 0) tlen = slen(u); int newlen = srclen + tlen + ulen; StrRep* rep; if (old == 0 || newlen > old->sz || (t >= old->s && t < &(old->s[old->len])) || (u >= old->s && u < &(old->s[old->len]))) rep = Snew(newlen); else rep = old; rep->len = newlen; ncopy(s, rep->s, srclen); ncopy(t, &(rep->s[srclen]), tlen); ncopy0(u, &(rep->s[srclen+tlen]), ulen); if (old != rep && old != 0) delete old; return rep; } // like cat, but we know that new stuff goes in the front of existing rep StrRep* Sprepend(StrRep* old, const char* t, int tlen) { char* s; int srclen; if (old == &_nilStrRep || old == 0) { s = 0; old = 0; srclen = 0; } else { s = old->s; srclen = old->len; } if (tlen < 0) tlen = slen(t); int newlen = srclen + tlen; StrRep* rep; if (old == 0 || newlen > old->sz || (t >= old->s && t < &(old->s[old->len]))) rep = Snew(newlen); else rep = old; rep->len = newlen; revcopy(&(s[srclen]), &(rep->s[newlen]), srclen+1); ncopy(t, rep->s, tlen); if (old != rep && old != 0) delete old; return rep; } // string compare: first argument is known to be non-null inline static int scmp(const char* a, const char* b) { if (b == 0) return *a != 0; else { signed char diff = 0; while ((diff = *a - *b++) == 0 && *a++ != 0); return diff; } } inline static int ncmp(const char* a, int al, const char* b, int bl) { int n = (al <= bl)? al : bl; signed char diff; while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff; return al - bl; } int fcompare(const String& x, const String& y) { const char* a = x.chars(); const char* b = y.chars(); int al = x.length(); int bl = y.length(); int n = (al <= bl)? al : bl; signed char diff = 0; while (n-- > 0) { char ac = *a++; char bc = *b++; if ((diff = ac - bc) != 0) { if (ac >= 'a' && ac <= 'z') ac = ac - 'a' + 'A'; if (bc >= 'a' && bc <= 'z') bc = bc - 'a' + 'A'; if ((diff = ac - bc) != 0) return diff; } } return al - bl; } // these are not inline, but pull in the above inlines, so are // pretty fast int compare(const String& x, const char* b) { return scmp(x.chars(), b); } int compare(const String& x, const String& y) { return scmp(x.chars(), y.chars()); } int compare(const String& x, const SubString& y) { return ncmp(x.chars(), x.length(), y.chars(), y.length()); } int compare(const SubString& x, const String& y) { return ncmp(x.chars(), x.length(), y.chars(), y.length()); } int compare(const SubString& x, const SubString& y) { return ncmp(x.chars(), x.length(), y.chars(), y.length()); } int compare(const SubString& x, const char* b) { if (b == 0) return x.length(); else { const char* a = x.chars(); int n = x.length(); signed char diff; while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff; return (*b == 0) ? 0 : -1; } } /* index fcts */ int String::search(int start, int sl, char c) const { const char* s = chars(); if (sl > 0) { if (start >= 0) { const char* a = &(s[start]); const char* lasta = &(s[sl]); while (a < lasta) if (*a++ == c) return --a - s; } else { const char* a = &(s[sl + start + 1]); while (--a >= s) if (*a == c) return a - s; } } return -1; } int String::search(int start, int sl, const char* t, int tl) const { const char* s = chars(); if (tl < 0) tl = slen(t); if (sl > 0 && tl > 0) { if (start >= 0) { const char* lasts = &(s[sl - tl]); const char* lastt = &(t[tl]); const char* p = &(s[start]); while (p <= lasts) { const char* x = p++; const char* y = t; while (*x++ == *y++) if (y >= lastt) return --p - s; } } else { const char* firsts = &(s[tl - 1]); const char* lastt = &(t[tl - 1]); const char* p = &(s[sl + start + 1]); while (--p >= firsts) { const char* x = p; const char* y = lastt; while (*x-- == *y--) if (y < t) return ++x - s; } } } return -1; } int String::match(int start, int sl, int exact, const char* t, int tl) const { if (tl < 0) tl = slen(t); if (start < 0) { start = sl + start - tl + 1; if (start < 0 || (exact && start != 0)) return -1; } else if (exact && sl - start != tl) return -1; if (sl == 0 || tl == 0 || sl - start < tl || start >= sl) return -1; int n = tl; const char* s = &(rep->s[start]); while (--n >= 0) if (*s++ != *t++) return -1; return tl; } void SubString::assign(StrRep* ysrc, const char* ys, int ylen) { if (&S == &_nilString) return; if (ylen < 0) ylen = slen(ys); StrRep* targ = S.rep; int sl = targ->len - len + ylen; if (ysrc == targ || sl >= targ->sz) { StrRep* oldtarg = targ; targ = Sresize(0, sl); ncopy(oldtarg->s, targ->s, pos); ncopy(ys, &(targ->s[pos]), ylen); scopy(&(oldtarg->s[pos + len]), &(targ->s[pos + ylen])); delete oldtarg; } else if (len == ylen) ncopy(ys, &(targ->s[pos]), len); else if (ylen < len) { ncopy(ys, &(targ->s[pos]), ylen); scopy(&(targ->s[pos + len]), &(targ->s[pos + ylen])); } else { revcopy(&(targ->s[targ->len]), &(targ->s[sl]), targ->len-pos-len +1); ncopy(ys, &(targ->s[pos]), ylen); } targ->len = sl; S.rep = targ; } // Regex stuff Regex::~Regex() { delete(buf->buffer); delete(buf->fastmap); delete(buf); delete(reg); } void Regex::initialize(const char* t, int tlen, int fast, int bufsize, const char* transtable) { if (tlen < 0) tlen = slen(t); buf = new re_pattern_buffer; reg = new re_registers; if (fast) buf->fastmap = new char[256]; else buf->fastmap = 0; buf->translate = (char*)transtable; if (tlen > bufsize) bufsize = tlen; buf->allocated = bufsize; buf->buffer = new char [buf->allocated]; char* msg = re_compile_pattern((char*)t, tlen, buf); if (msg != 0) (*lib_error_handler)("Regex", msg); else if (fast) re_compile_fastmap(buf); } int Regex::match_info(int& start, int& length, int nth) const { if ((unsigned)(nth) >= RE_NREGS) return 0; else { start = reg->start[nth]; length = reg->end[nth] - start; return start >= 0 && length >= 0; } } int Regex::search(const char* s, int len, int& matchlen, int startpos) const { int matchpos, pos, range; if (startpos >= 0) { pos = startpos; range = len - startpos; } else { pos = len + startpos; range = -pos; } matchpos = re_search_2(buf, 0, 0, (char*)s, len, pos, range, reg, len); if (matchpos >= 0) matchlen = reg->end[0] - reg->start[0]; else matchlen = 0; return matchpos; } int Regex::match(const char*s, int len, int p) const { if (p < 0) { p += len; if (p > len) return -1; return re_match_2(buf, 0, 0, (unsigned char*)s, p, 0, reg, p); } else if (p > len) return -1; else return re_match_2(buf, 0, 0, (unsigned char*)s, len, p, reg, len); } /* * substitution */ int String::_gsub(const char* pat, int pl, const char* r, int rl) { int nmatches = 0; if (pl < 0) pl = slen(pat); if (rl < 0) rl = slen(r); int sl = length(); if (sl <= 0 || pl <= 0 || sl < pl) return nmatches; const char* s = chars(); // prepare to make new rep StrRep* nrep = 0; int nsz = 0; char* x = 0; int si = 0; int xi = 0; int remaining = sl; while (remaining >= pl) { int pos = search(si, sl, pat, pl); if (pos < 0) break; else { ++nmatches; int mustfit = xi + remaining + rl - pl; if (mustfit >= nsz) { if (nrep != 0) nrep->len = xi; nrep = Sresize(nrep, mustfit); nsz = nrep->sz; x = nrep->s; } pos -= si; ncopy(&(s[si]), &(x[xi]), pos); ncopy(r, &(x[xi + pos]), rl); si += pos + pl; remaining -= pos + pl; xi += pos + rl; } } if (nrep == 0) { if (nmatches == 0) return nmatches; else nrep = Sresize(nrep, xi+remaining); } ncopy0(&(s[si]), &(x[xi]), remaining); nrep->len = xi + remaining; if (nrep->len <= rep->sz) // fit back in if possible { rep->len = nrep->len; ncopy0(nrep->s, rep->s, rep->len); delete(nrep); } else { delete(rep); rep = nrep; } return nmatches; } int String::_gsub(const Regex& pat, const char* r, int rl) { int nmatches = 0; int sl = length(); if (sl <= 0) return nmatches; if (rl < 0) rl = slen(r); const char* s = chars(); StrRep* nrep = 0; int nsz = 0; char* x = 0; int si = 0; int xi = 0; int remaining = sl; int pos, pl = 0; // how long is a regular expression? while (remaining > 0) { pos = pat.search(s, sl, pl, si); // unlike string search, the pos returned here is absolute if (pos < 0 || pl <= 0) break; else { ++nmatches; int mustfit = xi + remaining + rl - pl; if (mustfit >= nsz) { if (nrep != 0) nrep->len = xi; nrep = Sresize(nrep, mustfit); x = nrep->s; nsz = nrep->sz; } pos -= si; ncopy(&(s[si]), &(x[xi]), pos); ncopy(r, &(x[xi + pos]), rl); si += pos + pl; remaining -= pos + pl; xi += pos + rl; } } if (nrep == 0) { if (nmatches == 0) return nmatches; else nrep = Sresize(nrep, xi+remaining); } ncopy0(&(s[si]), &(x[xi]), remaining); nrep->len = xi + remaining; if (nrep->len <= rep->sz) // fit back in if possible { rep->len = nrep->len; ncopy0(nrep->s, rep->s, rep->len); delete(nrep); } else { delete(rep); rep = nrep; } return nmatches; } /* * deletion */ void String::del(int pos, int len) { if (pos < 0 || len <= 0 || pos + len > length()) return; int nlen = length() - len; int first = pos + len; ncopy0(&(rep->s[first]), &(rep->s[pos]), length() - first); rep->len = nlen; } void String::del(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); del(first, mlen); } void String::del(const char* t, int startpos) { int tlen = slen(t); int p = search(startpos, length(), t, tlen); del(p, tlen); } void String::del(const String& y, int startpos) { del(search(startpos, length(), y.chars(), y.length()), y.length()); } void String::del(const SubString& y, int startpos) { del(search(startpos, length(), y.chars(), y.length()), y.length()); } void String::del(char c, int startpos) { del(search(startpos, length(), c), 1); } /* * substring extraction */ SubString String::at(int first, int len) { return _substr(first, len); } SubString String::before(int pos) { return _substr(0, pos); } SubString String::through(int pos) { return _substr(0, pos+1); } SubString String::after(int pos) { return _substr(pos + 1, length() - (pos + 1)); } SubString String::from(int pos) { return _substr(pos, length() - pos); } SubString String::at(const String& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); return _substr(first, y.length()); } SubString String::at(const SubString& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); return _substr(first, y.length()); } SubString String::at(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); return _substr(first, mlen); } SubString String::at(const char* t, int startpos) { int tlen = slen(t); int first = search(startpos, length(), t, tlen); return _substr(first, tlen); } SubString String::at(char c, int startpos) { int first = search(startpos, length(), c); return _substr(first, 1); } SubString String::before(const String& y, int startpos) { int last = search(startpos, length(), y.chars(), y.length()); return _substr(0, last); } SubString String::before(const SubString& y, int startpos) { int last = search(startpos, length(), y.chars(), y.length()); return _substr(0, last); } SubString String::before(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); return _substr(0, first); } SubString String::before(char c, int startpos) { int last = search(startpos, length(), c); return _substr(0, last); } SubString String::before(const char* t, int startpos) { int tlen = slen(t); int last = search(startpos, length(), t, tlen); return _substr(0, last); } SubString String::through(const String& y, int startpos) { int last = search(startpos, length(), y.chars(), y.length()); if (last >= 0) last += y.length(); return _substr(0, last); } SubString String::through(const SubString& y, int startpos) { int last = search(startpos, length(), y.chars(), y.length()); if (last >= 0) last += y.length(); return _substr(0, last); } SubString String::through(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); if (first >= 0) first += mlen; return _substr(0, first); } SubString String::through(char c, int startpos) { int last = search(startpos, length(), c); if (last >= 0) last += 1; return _substr(0, last); } SubString String::through(const char* t, int startpos) { int tlen = slen(t); int last = search(startpos, length(), t, tlen); if (last >= 0) last += tlen; return _substr(0, last); } SubString String::after(const String& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); if (first >= 0) first += y.length(); return _substr(first, length() - first); } SubString String::after(const SubString& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); if (first >= 0) first += y.length(); return _substr(first, length() - first); } SubString String::after(char c, int startpos) { int first = search(startpos, length(), c); if (first >= 0) first += 1; return _substr(first, length() - first); } SubString String::after(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); if (first >= 0) first += mlen; return _substr(first, length() - first); } SubString String::after(const char* t, int startpos) { int tlen = slen(t); int first = search(startpos, length(), t, tlen); if (first >= 0) first += tlen; return _substr(first, length() - first); } SubString String::from(const String& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); return _substr(first, length() - first); } SubString String::from(const SubString& y, int startpos) { int first = search(startpos, length(), y.chars(), y.length()); return _substr(first, length() - first); } SubString String::from(const Regex& r, int startpos) { int mlen; int first = r.search(chars(), length(), mlen, startpos); return _substr(first, length() - first); } SubString String::from(char c, int startpos) { int first = search(startpos, length(), c); return _substr(first, length() - first); } SubString String::from(const char* t, int startpos) { int tlen = slen(t); int first = search(startpos, length(), t, tlen); return _substr(first, length() - first); } /* * split/join */ int split(const String& src, String results[], int n, const String& sep) { String x = src; const char* s = x.chars(); int sl = x.length(); int i = 0; int pos = 0; while (i < n && pos < sl) { int p = x.search(pos, sl, sep.chars(), sep.length()); if (p < 0) p = sl; results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos); i++; pos = p + sep.length(); } return i; } int split(const String& src, String results[], int n, const Regex& r) { String x = src; const char* s = x.chars(); int sl = x.length(); int i = 0; int pos = 0; int p, matchlen; while (i < n && pos < sl) { p = r.search(s, sl, matchlen, pos); if (p < 0) p = sl; results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos); i++; pos = p + matchlen; } return i; } String join(String src[], int n, const String& separator) return x; { String sep = separator; int xlen = 0; for (int i = 0; i < n; ++i) xlen += src[i].length(); xlen += (n - 1) * sep.length(); x.alloc(xlen); int j = 0; for (i = 0; i < n - 1; ++i) { ncopy(src[i].chars(), &(x.rep->s[j]), src[i].length()); j += src[i].length(); ncopy(sep.chars(), &(x.rep->s[j]), sep.length()); j += sep.length(); } ncopy0(src[i].chars(), &(x.rep->s[j]), src[i].length()); } /* misc */ StrRep* Sreverse(StrRep* src, StrRep* dest) { int n = src->len; if (src != dest) dest = Salloc(dest, src->s, n, n); if (n > 0) { char* a = dest->s; char* b = &(a[n - 1]); while (a < b) { char t = *a; *a++ = *b; *b-- = t; } } return dest; } StrRep* Supcase(StrRep* src, StrRep* dest) { int n = src->len; if (src != dest) dest = Salloc(dest, src->s, n, n); char* p = dest->s; char* e = &(p[n]); for (; p < e; ++p) if (islower(*p)) *p = toupper(*p); return dest; } StrRep* Sdowncase(StrRep* src, StrRep* dest) { int n = src->len; if (src != dest) dest = Salloc(dest, src->s, n, n); char* p = dest->s; char* e = &(p[n]); for (; p < e; ++p) if (isupper(*p)) *p = tolower(*p); return dest; } StrRep* Scapitalize(StrRep* src, StrRep* dest) { int n = src->len; if (src != dest) dest = Salloc(dest, src->s, n, n); char* p = dest->s; char* e = &(p[n]); for (; p < e; ++p) { int at_word; if (at_word = islower(*p)) *p = toupper(*p); else at_word = isupper(*p) || isdigit(*p); if (at_word) { while (++p < e) { if (isupper(*p)) *p = tolower(*p); else if (!islower(*p) && !isdigit(*p)) break; } } } return dest; } String replicate(char c, int n) return w; { w.rep = Sresize(w.rep, n); char* p = w.rep->s; while (n-- > 0) *p++ = c; *p = 0; } String replicate(const String& y, int n) return w { int len = y.length(); w.rep = Sresize(w.rep, n * len); char* p = w.rep->s; while (n-- > 0) { ncopy(y.chars(), p, len); p += len; } *p = 0; } String common_prefix(const String& x, const String& y, int startpos) return r; { const char* xchars = x.chars(); const char* ychars = y.chars(); const char* xs = &(xchars[startpos]); const char* ss = xs; const char* topx = &(xchars[x.length()]); const char* ys = &(ychars[startpos]); const char* topy = &(ychars[y.length()]); for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l); r.rep = Salloc(r.rep, ss, l, l); } String common_suffix(const String& x, const String& y, int startpos) return r; { const char* xchars = x.chars(); const char* ychars = y.chars(); const char* xs = &(xchars[x.length() + startpos]); const char* botx = xchars; const char* ys = &(ychars[y.length() + startpos]); const char* boty = ychars; for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l); r.rep = Salloc(r.rep, ++xs, l, l); } // IO istream& operator>>(istream& s, String& x) { if (!s.readable()) { s.set(_bad); return s; } char ch; int i = 0; x.rep = Sresize(x.rep, 20); s >> WS; if (!s.good()) { s.set(_bad); return s; } while (s.get(ch)) { if (isspace(ch)) break; if (i >= x.rep->sz - 1) x.rep = Sresize(x.rep, i+1); x.rep->s[i++] = ch; } x.rep->s[i] = 0; x.rep->len = i; s.failif(i == 0); return s; } int readline(istream& s, String& x, char terminator, int discard) { if (!s.readable()) { s.set(_bad); return 0; } char ch; int i = 0; x.rep = Sresize(x.rep, 80); while (s.get(ch)) { if (ch != terminator || !discard) { if (i >= x.rep->sz - 1) x.rep = Sresize(x.rep, i+1); x.rep->s[i++] = ch; } if (ch == terminator) break; } x.rep->s[i] = 0; x.rep->len = i; return i; } ostream& operator<<(ostream& s, const SubString& x) { const char* a = x.chars(); const char* lasta = &(a[x.length()]); while (a < lasta) s.put(*a++); return(s); } // from John.Willis@FAS.RI.CMU.EDU int String::freq(const SubString& y) const { int found = 0; for (int i = 0; i < length(); i++) if (match(i,length(),0,y.chars(), y.length())>= 0) found++; return(found); } int String::freq(const String& y) const { int found = 0; for (int i = 0; i < length(); i++) if (match(i,length(),0,y.chars(),y.length()) >= 0) found++; return(found); } int String::freq(const char* t) const { int found = 0; for (int i = 0; i < length(); i++) if (match(i,length(),0,t) >= 0) found++; return(found); } int String::freq(char c) const { int found = 0; for (int i = 0; i < length(); i++) if (match(i,length(),0,&c,1) >= 0) found++; return(found); } int String::OK() const { int v = rep != 0; // have a rep v &= rep->len <= rep->sz; // string within bounds v &= rep->s[rep->len] == 0; // null-terminated if (!v) error("invariant failure"); return v; } int SubString::OK() const { int v = S != 0; // have a String; v &= S.OK(); // that is legal v &= pos + len >= S.rep->len;// pos and len within bounds if (!v) S.error("SubString invariant failure"); return v; } int Regex::OK() const { // can't verify much, since we've lost the original string int v = buf != 0; // have a regex buf v &= buf->buffer != 0; // with a pat if (!v) (*lib_error_handler)("Regex", "invariant failure"); return v; } /* some built-in Regular expressions */ const Regex RXwhite("[ \n\t\r\v\f]+", 1); const Regex RXint("-?[0-9]+", 1); const Regex RXdouble("-?\\(\\([0-9]+\\.[0-9]*\\)\\|\\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\)\\([eE][---+]?[0-9]+\\)?", 1, 200); const Regex RXalpha("[A-Za-z]+", 1); const Regex RXlowercase("[a-z]+", 1); const Regex RXuppercase("[A-Z]+", 1); const Regex RXalphanum("[0-9A-Za-z]+", 1); const Regex RXidentifier("[A-Za-z_][A-Za-z0-9_]*", 1); error_handler)("Regex", "invariant failure"); return v; } /* some built-in Regular expressions */ const Regex RXwhite("[ \n\t\r\v\f]+", 1); const Regex RXint("-?[0-9]+", 1); const Regex RXdouble("-?\\(\\([0-9]+\\.[0-9]*\\)\\|\\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\)\\([eE][---+]?[0-9]+\\)?", 1, 200); const Regex RXalpha("[A-Za-z]+", 1); const Regex RXlowercase("[a-z]+", 1); const Regex RXuppercase("[A-Z]+", 1)libg++/src/Makefile 644 473 0 37212 4700614617 7407 # Makefile for libg++.a # Copyright (C) 1988 Free Software Foundation # written by Doug Lea (dl@rocky.oswego.edu) # This file is part of GNU CC. # GNU CC is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. No author or distributor # accepts responsibility to anyone for the consequences of using it # or for whether it serves any particular purpose or works at all, # unless he says so in writing. Refer to the GNU CC General Public # License for full details. # Everyone is granted permission to copy, modify and redistribute # GNU CC, but only under the conditions described in the # GNU CC General Public License. A copy of this license is # supposed to have been given to you along with GNU CC so you # can know your rights and responsibilities. It should be in a # file named COPYING. Among other things, the copyright notice # and this notice must be preserved on all copies. # make parameters -- these should normally be inherited from parent make # ------ source locations # source directory for libg++.a SRCDIR = ../src # source include directory SRCIDIR= ../g++-include # ------ installation destinations # ------ You will require write-permission on the destination directories # ------ in order to `make install' prefix =/usr/local # libg++.a destination LIBDIR = $(prefix)/lib # executables directory: location to install the genclass class generator BINDIR = $(prefix)/bin # location to install include file directory IDIR = $(prefix)/lib/g++-include # ------- System-dependent defines # ------- use the second form of each for SystemV (USG) # g++ flags OSFLAG= #OSFLAG = -DUSG # use this only if you have a strange stdio implementation #OSFLAG = -DDEFAULT_filebuf # ld or ld++ flags OSLDFLAG = #OSLDFLAG= -lPW # how to install INSTALL=install -c #INSTALL=cp # ranlib if necessary RANLIB=gnuranlib #RANLIB=echo # which make? MAKE=make # not used, but convenient for those who preprocess things while compiling SHELL=/bin/sh # ------ compiler names # GNU C++ compiler name GXX = g++ #GXX=gcc # GNU CC compiler name (needed for some .c files in libg++.a) CC = gcc # GNU loader LDXX = $(LIBDIR)/gcc-ld++ # crt0+.o location (for dynamic loading tests) GXXCRT1=$(LIBDIR)/crt1+.o # ------ Other compilation flags # ------ modify as you like -- the ones here are sheer overkill GXX_OPTIMIZATION_FLAGS= -O -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized GCC_OPTIMIZATION_FLAGS= -O -fstrength-reduce -fdelayed-branch DEBUG_FLAGS= -g #use this only if you like to look at lots of useless messages VERBOSITY_FLAGS= -Wall -v GXX_INCLUDE_DIRS= -I$(SRCIDIR) GCC_INCLUDE_DIRS= -I$(prefix)/lib/gcc-include -I/usr/include -I$(SRCIDIR) PIPE_AS= -pipe # Flags for all C++ compiles GXXFLAGS = $(OSFLAG) $(GXX_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GXX_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # Flags for all C compiles CFLAGS= $(OSFLAG) $(GCC_INCLUDE_DIRS) $(DEBUG_FLAGS) $(GCC_OPTIMIZATION_FLAGS) $(VERBOSITY_FLAGS) $(PIPE_AS) # g++ load time flags GXXLDFLAGS = -L$(SRCDIR) -lg++ -lm $(OSLDFLAG) # these flags tell test0 where ld++ and crt1+.o are TFLAGS = -DLDXX=\"$(LDXX)\" -DCRT1X=\"$(GXXCRT1)\" # g++ files should have extension .cc .SUFFIXES: .cc .cc.o: $(GXX) $(GXXFLAGS) -c $< ########################################################################### # # declarations from here on should not normally need to be changed # in order to compile libg++.a # # library sources SRCS = AllocRing.cc Obstack.cc File.cc \ ostream.cc istream.cc streambuf.cc filebuf.cc Filebuf.cc \ PlotFile.cc SFile.cc \ regex.cc String.cc Integer.cc Rational.cc Complex.cc \ BitSet.cc BitString.cc Normal.cc NegExp.cc Weibell.cc Erlang.cc DiscUnif.cc \ Uniform.cc Poisson.cc HyperGeo.cc Geometric.cc Binomial.cc \ RNG.cc ACG.cc MLCG.cc Sample.cc \ Fix.cc Fix16.cc Fix24.cc Curses.cc GetOpt.cc gnulib3.c EH.cc EH2.c \ malloc.c new.cc delete.cc xyzzy.cc chr.cc dtoa.cc error.cc \ form.cc gcd.cc hash.cc itoa.cc \ lg.cc libgxx_fmtq.cc libgxx_ob.cc pow.cc sqrt.cc str.cc timer.cc OBJS = AllocRing.o Obstack.o File.o ostream.o istream.o \ streambuf.o filebuf.o Filebuf.o \ PlotFile.o SFile.o \ regex.o String.o Integer.o Rational.o Complex.o \ BitSet.o BitString.o \ Normal.o NegExp.o Weibell.o Erlang.o DiscUnif.o \ Uniform.o Poisson.o HyperGeo.o Geometric.o Binomial.o \ RNG.o ACG.o MLCG.o Sample.o \ Fix.o Fix16.o Fix24.o Curses.o GetOpt.o EH.o EH2.o\ xyzzy.o gnulib3.o new.o delete.o malloc.o chr.o dtoa.o error.o form.o gcd.o \ hash.o itoa.o \ lg.o libgxx_fmtq.o libgxx_ob.o pow.o sqrt.o str.o timer.o ########################################################################### # # compilation actions # all: libg++.a libg++.a: $(OBJS) rm -f libg++.a ar r libg++.a $(OBJS) $(RANLIB) libg++.a clean: rm -f *.o core libg++.a C++.hack* ########################################################################### # # dependencies # # DO NOT DELETE THIS LINE -- g++dep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ACG.o : ACG.cc $(SRCIDIR)/ACG.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h AllocRing.o : AllocRing.cc $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/AllocRing.h $(SRCIDIR)/new.h Binomial.o : Binomial.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Binomial.h BitSet.o : BitSet.cc $(SRCIDIR)/BitSet.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Obstack.h \ $(SRCIDIR)/AllocRing.h $(SRCIDIR)/new.h BitString.o : BitString.cc $(SRCIDIR)/BitString.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Obstack.h \ $(SRCIDIR)/AllocRing.h $(SRCIDIR)/new.h Complex.o : Complex.cc $(SRCIDIR)/Complex.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h Curses.o : Curses.cc $(SRCIDIR)/stdio.h \ $(SRCIDIR)/stdarg.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/CursesWindow.h $(SRCIDIR)/curses.h DiscUnif.o : DiscUnif.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/DiscreteUniform.h EH.o : EH.cc $(SRCIDIR)/setjmp.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h EH2.o : EH2.c Erlang.o : Erlang.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Erlang.h File.o : File.cc $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/stdarg.h $(SRCIDIR)/sys/file.h \ $(SRCIDIR)/sys/types.h Filebuf.o : Filebuf.cc $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/File.h $(SRCIDIR)/sys/file.h \ $(SRCIDIR)/sys/types.h Fix.o : Fix.cc $(SRCIDIR)/Fix.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/Integer.h \ $(SRCIDIR)/Obstack.h $(SRCIDIR)/AllocRing.h Fix16.o : Fix16.cc $(SRCIDIR)/Fix16.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h Fix24.o : Fix24.cc $(SRCIDIR)/Fix24.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h Geometric.o : Geometric.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Geometric.h GetOpt.o : GetOpt.cc $(SRCIDIR)/GetOpt.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h HyperGeo.o : HyperGeo.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/HyperGeometric.h Integer.o : Integer.cc $(SRCIDIR)/Integer.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/ctype.h \ $(SRCIDIR)/Obstack.h $(SRCIDIR)/AllocRing.h \ $(SRCIDIR)/new.h MLCG.o : MLCG.cc $(SRCIDIR)/MLCG.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h Normal.o : Normal.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Normal.h $(SRCIDIR)/LogNormal.h NegExp.o : NegExp.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/NegativeExpntl.h Obstack.o : Obstack.cc $(SRCIDIR)/values.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/Obstack.h PlotFile.o : PlotFile.cc $(SRCIDIR)/PlotFile.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h Poisson.o : Poisson.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Poisson.h RNG.o : RNG.cc $(SRCIDIR)/values.h \ $(SRCIDIR)/assert.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/RNG.h Rational.o : Rational.cc $(SRCIDIR)/Rational.h \ $(SRCIDIR)/Integer.h $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h SFile.o : SFile.cc $(SRCIDIR)/SFile.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h Sample.o : Sample.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/SampleStatistic.h \ $(SRCIDIR)/SampleHistogram.h String.o : String.cc $(SRCIDIR)/String.h \ $(SRCIDIR)/stream.h $(SRCIDIR)/File.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/streambuf.h $(SRCIDIR)/ctype.h \ $(SRCIDIR)/new.h $(SRCIDIR)/regex.h Uniform.o : Uniform.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Uniform.h Weibell.o : Weibell.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/Random.h \ $(SRCIDIR)/RNG.h $(SRCIDIR)/assert.h \ $(SRCIDIR)/Weibull.h chr.o : chr.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/AllocRing.h dtoa.o : dtoa.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/AllocRing.h error.o : error.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h filebuf.o : filebuf.cc $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/File.h $(SRCIDIR)/sys/file.h \ $(SRCIDIR)/sys/types.h form.o : form.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/stdarg.h \ $(SRCIDIR)/AllocRing.h gcd.o : gcd.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h hash.o : hash.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h istream.o : istream.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/stdarg.h $(SRCIDIR)/ctype.h \ $(SRCIDIR)/Obstack.h itoa.o : itoa.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/AllocRing.h lg.o : lg.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h libgxx_fmtq.o : libgxx_fmtq.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/AllocRing.h libgxx_ob.o : libgxx_ob.cc $(SRCIDIR)/Obstack.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/stdio.h new.o : new.cc $(SRCIDIR)/stddef.h \ $(SRCIDIR)/malloc.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h ostream.o : ostream.cc $(SRCIDIR)/stream.h \ $(SRCIDIR)/File.h $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/stdarg.h $(SRCIDIR)/ctype.h \ $(SRCIDIR)/Obstack.h pow.o : pow.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h regex.o : regex.cc $(SRCIDIR)/std.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/malloc.h $(SRCIDIR)/regex.h sqrt.o : sqrt.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h str.o : str.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/AllocRing.h streambuf.o : streambuf.cc $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/File.h timer.o : timer.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/osfcn.h \ $(SRCIDIR)/time.h $(SRCIDIR)/sys/types.h \ $(SRCIDIR)/sys/socket.h $(SRCIDIR)/sys/resource.h xyzzy.o : xyzzy.cc # IF YOU PUT ANYTHING HERE IT WILL GO AWAY eambuf.cc $(SRCIDIR)/streambuf.h \ $(SRCIDIR)/builtin.h $(SRCIDIR)/stddef.h \ $(SRCIDIR)/std.h $(SRCIDIR)/stdio.h \ $(SRCIDIR)/math.h $(SRCIDIR)/values.h \ $(SRCIDIR)/File.h timer.o : timer.cc $(SRCIDIR)/builtin.h \ $(SRCIDIR)/stddef.h $(SRCIDIR)/std.h \ $(SRCIDIR)/stdio.h $(SRCIDIR)/math.h \ $(SRCIDIR)/values.h $(SRCIDIR)/osfcn.h \ $(SRCIDIR)/time.h $(SRlibg++/src/gnulib3.c 644 473 0 3326 4677700050 7435 #ifndef NO_GNULIB3 /* skip entire file if NO_GNULIB3 */ typedef struct set_vector { int length; int vector[1]; /* struct set_vector *next; */ } set_vector; extern set_vector __CTOR_LIST__; extern set_vector __DTOR_LIST__; set_vector *__dlp; int __dli; extern void exit (int); extern void __do_global_init (); extern void __do_global_cleanup (); extern void on_exit(void*, void*); extern void _cleanup(); extern void _exit(int); #if defined(i386) && !defined(sequent) #define COFF #endif #ifdef COFF_ENCAPSULATE #undef COFF #endif /* ON_EXIT macro commented out - dl Sun on_exit doesn't get linked in right!!! */ #if 0 #if defined(sun) #define ON_EXIT(PROCP, ARG) \ do { extern void PROCP (); on_exit (PROCP, ARG); } while (0) #endif #endif int __main () { /* Gross hack for GNU ld. This is defined in `builtin.cc' from libg++. */ #ifndef COFF extern int __1xyzzy__; #endif #ifdef ON_EXIT #ifdef sun ON_EXIT (_cleanup, 0); #endif ON_EXIT (__do_global_cleanup, 0); #endif __dli = __DTOR_LIST__.length; __dlp = &__DTOR_LIST__; #ifndef COFF __do_global_init (&__1xyzzy__); #else __do_global_init (); #endif } #ifndef ON_EXIT void exit (status) int status; { __do_global_cleanup (); _cleanup (); _exit (status); } #endif void __do_global_init () { register int i, len; register void (**ppf)() = (void (**)())__CTOR_LIST__.vector; len = __CTOR_LIST__.length; for (i = 0; i < len; i++) (*ppf[i])(); } void __do_global_cleanup () { while (__dlp) { while (--__dli >= 0) { void (*pf)() = (void (*)())__dlp->vector[__dli]; (*pf)(); } __dlp = (struct set_vector *)__dlp->vector[__dlp->length]; if (__dlp) __dli = __dlp->length; } } #endif up (); _cleanup (); _exit (status); } #endif void __do_global_init () { register int i, len; register void (**ppf)() = (void (**)())__CTOR_LIST__.vector; len = __CTOR_LIST__.length; for (i = 0; i < len; i++) (*ppf[i])(); } void __do_global_cleanup () { while (__dlp) { libg++/src/Curses.cc 655 473 0 11476 4677700051 7531 /* Copyright (C) 1989 Free Software Foundation written by Eric Newton (newton@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include #include /* * C++ interface to curses library. * */ /* * varargs functions are handled conservatively: * They interface directly into the underlying * _doscan, _doprnt and/or vfprintf routines rather than * assume that such things are handled compatibly in the curses library */ int CursesWindow::scanw(const char * fmt, ...) { va_list args; va_start(args, fmt); char buf[BUFSIZ]; FILE b; b._flag = _IOREAD|_IOSTRG; b._base = buf; b._ptr = buf; b._cnt = BUFSIZ; int result = wgetstr(w, buf); if (result == OK) result = _doscan(&b, fmt, args); va_end(args); return result; } int CursesWindow::mvscanw(int y, int x, const char * fmt, ...) { va_list args; va_start(args, fmt); char buf[BUFSIZ]; FILE b; b._flag = _IOREAD|_IOSTRG; b._base = buf; b._ptr = buf; b._cnt = BUFSIZ; int result = wmove(w, y, x); if (result == OK) { result = wgetstr(w, buf); if (result == OK) result = _doscan(&b, fmt, args); } va_end(args); return result; } int CursesWindow::printw(const char * fmt, ...) { va_list args; va_start(args, fmt); char buf[BUFSIZ]; #ifndef HAVE_VPRINTF FILE b; b._flag = _IOWRT|_IOSTRG; b._ptr = buf; b._cnt = BUFSIZ; _doprnt(fmt, args, &b); putc('\0', &b); #else vsprintf(buf, fmt, args); #endif va_end(args); return waddstr(w, buf); } int CursesWindow::mvprintw(int y, int x, const char * fmt, ...) { va_list args; va_start(args, fmt); char buf[BUFSIZ]; int result = wmove(w, y, x); if (result == OK) { #ifndef HAVE_VPRINTF FILE b; b._flag = _IOWRT|_IOSTRG; b._ptr = buf; b._cnt = BUFSIZ; _doprnt(fmt, args, &b); putc('\0', &b); #else vsprintf(buf, fmt, args); #endif result = waddstr(w, buf); } va_end(args); return result; } CursesWindow::CursesWindow(int lines, int cols, int begin_y, int begin_x) { if (count==0) initscr(); w = newwin(lines, cols, begin_y, begin_x); if (w == 0) { (*lib_error_handler)("CursesWindow", "Cannot construct window"); } alloced = 1; subwins = par = sib = 0; count++; } CursesWindow::CursesWindow(WINDOW* &window) { if (count==0) initscr(); w = window; alloced = 0; subwins = par = sib = 0; count++; } CursesWindow::CursesWindow(CursesWindow& win, int l, int c, int by, int bx, char absrel) { if (absrel == 'r') // relative origin { by += win.begy(); bx += win.begx(); } // Even though we treat subwindows as a tree, the standard curses // library needs the `subwin' call to link to the root in // order to correctly perform refreshes, etc. CursesWindow* root = &win; while (root->par != 0) root = root->par; w = subwin(root->w, l, c, by, bx); if (w == 0) { (*lib_error_handler)("CursesWindow", "Cannot construct subwindow"); } par = &win; sib = win.subwins; win.subwins = this; subwins = 0; alloced = 1; count++; } void CursesWindow::kill_subwindows() { for (CursesWindow* p = subwins; p != 0; p = p->sib) { p->kill_subwindows(); if (p->alloced) { if (p->w != 0) ::delwin(p->w); p->alloced = 0; } p->w = 0; // cause a run-time error if anyone attempts to use... } } CursesWindow::~CursesWindow() { kill_subwindows(); if (par != 0) // Snip us from the parent's list of subwindows. { CursesWindow * win = par->subwins; CursesWindow * trail = 0; for (;;) { if (win == 0) break; else if (win == this) { if (trail != 0) trail->sib = win->sib; else par->subwins = win->sib; break; } else { trail = win; win = win->sib; } } } if (alloced && w != 0) delwin(w); --count; if (count == 0) endwin(); else if (count < 0) // cannot happen! { (*lib_error_handler)("CursesWindow", "Too many windows destroyed"); } } ; for (;;) { if (win == 0) break; else if (win == this) { if (trail != 0) trail->sib = win->sib; else par->subwins = win->silibg++/src/Fix16.cc 644 473 0 13442 4677700051 7153 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ // // Fix.cc : fixed precision class support functions // #include // basic operators too large to be inline short Fix16::assign(double d) { if (d == 1.0) return Fix16_m_max; else if (d > Fix16_max) { short i = Fix16_m_max; range_error(i); return i; } else if (d < Fix16_min) { short i = Fix16_m_min; range_error(i); return i; } else return round(Fix16_mult * d); } long Fix32::assign(double d) { if (d == 1.0) return Fix32_m_max; else if (d > Fix32_max) { long i = Fix32_m_max; range_error(i); return i; } else if (d < Fix32_min) { long i = Fix32_m_min; range_error(i); return i; } else return round(Fix32_mult * d); } Fix32 operator * (Fix32& a, Fix32& b) { // break a and b into lo and hi parts, and do a multiple-precision // multiply, with rounding int apos = (a.m >= 0); unsigned long ua = (apos)? a.m : - a.m; ua <<= 1; // ua is biased so result will be 31 bit mantissa, not 30: unsigned long hi_a = (ua >> 16) & ((1 << 16) - 1); unsigned long lo_a = ua & ((1 << 16) - 1); int bpos = (b.m >= 0); unsigned long ub = (bpos)? b.m : -b.m; unsigned long hi_b = (ub >> 16) & ((1 << 16) - 1); unsigned long lo_b = ub & ((1 << 16) - 1); unsigned long r = lo_a * lo_b + (1 << 15); r = (r >> 16) + hi_a * lo_b + lo_a * hi_b + (1 << 15); r = (r >> 16) + hi_a * hi_b; long p = (apos != bpos)? -r : r; return Fix32(p); } Fix16 operator / (Fix16& a, Fix16& b) { short q; int apos = (a.m >= 0); long la = (apos)? a.m : -a.m; long scaled_a = la << 15; int bpos = (b.m >= 0); short sb = (bpos)? b.m: -b.m; if (la >= sb) { q = (apos == bpos)? Fix16_m_max: Fix16_m_min; a.range_error(q); } else { q = scaled_a / sb; if ((scaled_a % sb) >= (sb / 2)) ++q; if (apos != bpos) q = -q; } return Fix16(q); } Fix32 operator / (Fix32& a, Fix32& b) { long q; int apos = (a.m >= 0); unsigned long la = (apos)? a.m : -a.m; int bpos = (b.m >= 0); unsigned long lb = (bpos)? b.m: -b.m; if (la >= lb) { q = (apos == bpos)? Fix32_m_max: Fix32_m_min; a.range_error(q); } else // standard shift-based division alg { q = 0; long r = la; for (int i = 32; i > 0; i--) { if (r > lb) { q = (q << 1) | 1; r -= lb; } else q = (q << 1); r <<= 1; } if (apos != bpos) q = -q; // Fix sign } return Fix32(q); } // error handling void Fix16::overflow(short& i) { (*Fix16_overflow_handler)(i); } void Fix32::overflow(long& i) { (*Fix32_overflow_handler)(i); } void Fix16::range_error(short& i) { (*Fix16_range_error_handler)(i); } void Fix32::range_error(long& i) { (*Fix32_range_error_handler)(i); } // data definitions Fix16_peh Fix16_overflow_handler = Fix16_overflow_saturate; Fix32_peh Fix32_overflow_handler = Fix32_overflow_saturate; Fix16_peh Fix16_range_error_handler = Fix16_warning; Fix32_peh Fix32_range_error_handler = Fix32_warning; //function definitions Fix16_peh set_Fix16_overflow_handler(Fix16_peh new_handler) { Fix16_peh old_handler = Fix16_overflow_handler; Fix16_overflow_handler = new_handler; return old_handler; } Fix32_peh set_Fix32_overflow_handler(Fix32_peh new_handler) { Fix32_peh old_handler = Fix32_overflow_handler; Fix32_overflow_handler = new_handler; return old_handler; } void set_overflow_handler(Fix16_peh handler16, Fix32_peh handler32) { set_Fix16_overflow_handler(handler16); set_Fix32_overflow_handler(handler32); } Fix16_peh set_Fix16_range_error_handler(Fix16_peh new_handler) { Fix16_peh old_handler = Fix16_range_error_handler; Fix16_range_error_handler = new_handler; return old_handler; } Fix32_peh set_Fix32_range_error_handler(Fix32_peh new_handler) { Fix32_peh old_handler = Fix32_range_error_handler; Fix32_range_error_handler = new_handler; return old_handler; } void set_range_error_handler(Fix16_peh handler16, Fix32_peh handler32) { set_Fix16_range_error_handler(handler16); set_Fix32_range_error_handler(handler32); } void Fix16_overflow_saturate(short& i) { i = (i > 0 ? Fix16_m_min : Fix16_m_max); } void Fix16_ignore(short&) {} void Fix16_warning(short&) { cerr << "warning: Fix16 result out of range\n"; } void Fix16_overflow_warning_saturate(short& i) { cerr << "warning: Fix16 result out of range\n"; Fix16_overflow_saturate(i); } void Fix16_abort(short&) { cerr << "error: Fix16 result out of range\n"; abort(); } void Fix32_ignore(long&) {} void Fix32_overflow_saturate(long& i) { i = (i > 0 ? Fix32_m_min : Fix32_m_max); } void Fix32_warning(long&) { cerr << "warning: Fix32 result out of range\n"; } void Fix32_overflow_warning_saturate(long& i) { cerr << "warning: Fix32 result out of range\n"; Fix32_overflow_saturate(i); } void Fix32_abort(long&) { cerr << "error: Fix32 result out of range\n"; abort(); } turate(i); } void Fix16_abort(short&) { cerr << "error: Fix16 result out of range\n"; abort(); } void Fix32_ignore(long&) {} void Fix32_overflow_saturate(long& i) { i = (i > 0 ? Fix32_m_min : Fix32_m_max); } void Fix3libg++/src/Fix24.cc 644 473 0 21355 4677700051 7154 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) adapted for libg++ by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ // // Fix24.cc : fixed precision class support functions // #include const int Fix24_shift = 31; const double Fix24_fs = 2147483648., // 2^Fix24_shift Fix24_mult = Fix24_fs, Fix24_div = 1./Fix24_fs, Fix24_max = 1. - .5/Fix24_fs, Fix24_min = -1.; const unsigned long Fix24_msb = 0x80000000L, Fix24_lsb = 0x00000100L, Fix24_m_max = 0x7fffff00L, Fix24_m_min = 0x80000000L; const double Fix48_fs = 36028797018963968., // 2^(24+Fix24_shift) Fix48_max = 1. - .5/Fix48_fs, Fix48_min = -1., Fix48_div_u = 1./Fix24_fs, Fix48_div_l = 1./Fix48_fs; const twolongs Fix48_msb = { 0x80000000L, 0L }, Fix48_lsb = { 0L, 0x00000100L }, Fix48_m_max = { 0x7fffff00L, 0xffffff00L }, Fix48_m_min = { 0x80000000L, 0L }; // basic operators too large to be inline long Fix24::assign(double d) { if (d == 1.0) return Fix24_m_max; else if (d > Fix24_max) { long i = Fix24_m_max; range_error(i); return i; } else if (d < Fix24_min) { long i = Fix24_m_min; range_error(i); return i; } else { d = (long) (d * (1 << 24) + ((d >= 0)? 0.5 : -0.5)); // Round to 24 bits return ((long) d) << (Fix24_shift - 24); /* Convert to integer format */ } } twolongs Fix48::assign(double d) { if (d == 1.0) return Fix48_m_max; else if (d > Fix48_max) { twolongs i = Fix48_m_max; range_error(i); return i; } else if (d < Fix48_min) { twolongs i = Fix48_m_min; range_error(i); return i; } else { twolongs i; int sign = (d < 0); /* First, convert the absolute value of d to a 48-bit integer format */ if (d < 0) d = -d; i.u = ((long)(d *= Fix24_mult)) & 0xffffff00; i.l = ((unsigned long)((d - i.u)* (Fix24_mult / (1 << 7)))) & 0xffffff00; /* Calculate the two's complement if d was negative */ if (sign) { unsigned long oldlower = i.l; i.l = (~i.l + 1) & 0xffffff00; i.u = (~i.u + (((oldlower ^ i.l) & Fix24_msb)? 0 : 1)) & 0xffffff00; } return i; } } Fix48 operator * (Fix24& a, Fix24& b) { // break a and b into lo and hi parts, and do a multiple-precision // multiply, with rounding int apos = (a.m >= 0); unsigned long ua = (apos)? a.m : - a.m; ua <<= 1; // ua is biased so result will be 47 bit mantissa, not 46: unsigned long hi_a = (ua >> 16) & ((1 << 16) - 1); unsigned long lo_a = ua & ((1 << 16) - 1); int bpos = (b.m >= 0); unsigned long ub = (bpos)? b.m : -b.m; unsigned long hi_b = (ub >> 16) & ((1 << 16) - 1); unsigned long lo_b = ub & ((1 << 16) - 1); unsigned long hi_r = hi_a * hi_b, mi_r = hi_a * lo_b + lo_a * hi_b, lo_r = lo_a * lo_b, rl = ((hi_r << 16) & 0x00ffffffL) + (mi_r & 0x00ffffffL) + (lo_r >> 16); twolongs r; r.u = (hi_r & 0xffffff00L) + ((mi_r >> 16) & 0x0000ff00L) + ((rl >> 16) & 0x0000ff00L); r.l = rl << 8; if ( apos != bpos ) { unsigned long l = r.l; r.l = -r.l; r.u = (~r.u + ((l ^ r.l) & Fix24_msb ? 0 : Fix24_lsb)) & 0xffffff00; } return r; } Fix24 operator / (Fix24& a, Fix24& b) { long q; int apos = (a.m >= 0); unsigned long la = (apos)? a.m : -a.m; int bpos = (b.m >= 0); unsigned long lb = (bpos)? b.m: -b.m; if (la >= lb) { q = (apos == bpos)? Fix24_m_max: Fix24_m_min; a.range_error(q); } else // standard shift-based division alg { q = 0; long r = la; for (int i = 32; i > 0; i--) { if (r > lb) { q = (q << 1) | 1; r -= lb; } else q = (q << 1); r <<= 1; } q += 0x80; // Round result to 24 bits if (apos != bpos) q = -q; // Fix sign } return (q & 0xffffff00); } Fix48 operator + (Fix48& f, Fix48& g) { long lo_r = (f.m.l >> 8) + (g.m.l >> 8); twolongs r; r.u = f.m.u + g.m.u + (lo_r & 0x01000000L ? 0x00000100L : 0); r.l = lo_r << 8; if ( (f.m.u ^ r.u) & (g.m.u ^ r.u) & Fix24_msb ) f.overflow(r); return r; } Fix48 operator - (Fix48& f, Fix48& g) { unsigned lo_r = (f.m.l >> 8) - (g.m.l >> 8); twolongs r; r.u = f.m.u - g.m.u - (lo_r & 0x01000000L ? 0x00000100L: 0); r.l = lo_r << 8; if ( ((f.m.u ^ r.u) & (-g.m.u ^ r.u) & Fix24_msb) && g.m.u ) f.overflow(r); return r; } Fix48 operator * (Fix48& a, int b) { twolongs r; int bpos = (b >= 0); unsigned ub = (bpos)? b : -b; if ( ub >= 65536L ) { r = (bpos)? Fix48_m_max : Fix48_m_min; a.range_error(r); } else { unsigned long lo_r = (a.m.l & 0xffff) * ub, mi_r = ((a.m.l >> 16) & 0xffff) * ub, hi_r = a.m.u * ub; r.l = lo_r + (mi_r << 16); r.u = hi_r + ((mi_r >> 8) & 0x00ffff00L); if ( !bpos ) { unsigned long l = r.l; r.l = -r.l; r.u = ~r.u + ((l ^ r.l) & Fix24_msb ? 0 : Fix24_lsb); } } return r; } Fix48 operator << (Fix48& a, int b) { twolongs r; r.u = r.l = 0; if ( b >= 0 ) if ( b < 24 ) { r.u = (a.m.u << b) + ((a.m.l >> (24 - b)) & 0xffffff00L); r.l = a.m.l << b; } else if ( b < 48 ) { r.u = a.m.l << (b - 24); } return r; } Fix48 operator >> (Fix48& a, int b) { twolongs r; r.u = r.l = 0; if ( b >= 0 ) if ( b < 24 ) { r.l = (a.m.u << (24 - b)) + ((a.m.l >> b) & 0xffffff00L); r.u = (a.m.u >> b) & 0xffffff00L; } else if ( b < 48 ) { r.l = (a.m.u >> (b - 24)) & 0xffffff00L; r.u = (a.m.u >> 24) & 0xffffff00L; } else { r.l = (a.m.u >> 24) & 0xffffff00L; r.u = r.l; } return r; } // error handling void Fix24::overflow(long& i) { (*Fix24_overflow_handler)(i); } void Fix48::overflow(twolongs& i) { (*Fix48_overflow_handler)(i); } void Fix24::range_error(long& i) { (*Fix24_range_error_handler)(i); } void Fix48::range_error(twolongs& i) { (*Fix48_range_error_handler)(i); } // data definitions Fix24_peh Fix24_overflow_handler = Fix24_overflow_saturate; Fix48_peh Fix48_overflow_handler = Fix48_overflow_saturate; Fix24_peh Fix24_range_error_handler = Fix24_warning; Fix48_peh Fix48_range_error_handler = Fix48_warning; //function definitions Fix24_peh set_Fix24_overflow_handler(Fix24_peh new_handler) { Fix24_peh old_handler = Fix24_overflow_handler; Fix24_overflow_handler = new_handler; return old_handler; } Fix48_peh set_Fix48_overflow_handler(Fix48_peh new_handler) { Fix48_peh old_handler = Fix48_overflow_handler; Fix48_overflow_handler = new_handler; return old_handler; } void set_overflow_handler(Fix24_peh handler24, Fix48_peh handler48) { set_Fix24_overflow_handler(handler24); set_Fix48_overflow_handler(handler48); } Fix24_peh set_Fix24_range_error_handler(Fix24_peh new_handler) { Fix24_peh old_handler = Fix24_range_error_handler; Fix24_range_error_handler = new_handler; return old_handler; } Fix48_peh set_Fix48_range_error_handler(Fix48_peh new_handler) { Fix48_peh old_handler = Fix48_range_error_handler; Fix48_range_error_handler = new_handler; return old_handler; } void set_range_error_handler(Fix24_peh handler24, Fix48_peh handler48) { set_Fix24_range_error_handler(handler24); set_Fix48_range_error_handler(handler48); } void Fix24_overflow_saturate(long& i) { i = (i > 0 ? Fix24_m_min : Fix24_m_max); } void Fix24_ignore(long&) {} void Fix24_warning(long&) { cerr << "warning: Fix24 result out of range\n"; } void Fix24_overflow_warning_saturate(long& i) { cerr << "warning: Fix24 result out of range\n"; Fix24_overflow_saturate(i); } void Fix24_abort(long&) { cerr << "error: Fix24 result out of range\n"; abort(); } void Fix48_ignore(twolongs&) {} void Fix48_overflow_saturate(twolongs& i) { i = (i.u > 0 ? Fix48_m_min : Fix48_m_max); } void Fix48_warning(twolongs&) { cerr << "warning: Fix48 result out of range\n"; } void Fix48_overflow_warning_saturate(twolongs& i) { cerr << "warning: Fix48 result out of range\n"; Fix48_overflow_saturate(i); } void Fix48_abort(twolongs&) { cerr << "error: Fix48 result out of range\n"; abort(); } 24_abort(long&) { cerr << "error: Fix24 result out of range\n"; abort(); } void Fix48_ignore(twolongs&) {} void Fix48_overflow_saturate(twolongs& i) { i = (i.u > 0 ? Fix48_m_min : Fix48_m_max); } void Fix48_warning(twolongs&) { cerr << "warning: Fix48 result out of ralibg++/src/streambuf.cc 644 473 0 5056 4677700051 10230 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include streambuf::streambuf() :base(0), gptr(0), pptr(0), eptr(0), alloc(0) {} streambuf::streambuf(char* buf, int buflen) : base(buf), gptr(buf), pptr(buf), eptr(buf+buflen-1), alloc(0) {} streambuf::~streambuf() { if (alloc && (base != 0)) delete base; } int streambuf::doallocate() { if (alloc && base != 0) delete base; base = new char[BUFSIZ]; gptr = pptr = base; eptr = base + BUFSIZ - 1; alloc = 1; return BUFSIZ; } streambuf* streambuf::setbuf(char* buf, int buflen, int preloaded_count) { base = gptr = buf; pptr = base + preloaded_count; eptr = base + buflen - 1; return this; } const char* streambuf::name() { return 0; } int streambuf::overflow(int c) { if (base == 0) allocate(); return (c == EOF)? c : ((pptr <= eptr)? (*pptr++ = (char)(c)) : EOF); } int streambuf::underflow() { return EOF; } int streambuf::sputs(const char* s) { if (s != 0) { for(; *s != 0; ++s) { if (must_overflow(*s)) { if (overflow(*s) == EOF) return EOF; } else *pptr++ = *s; } } return 0; } int streambuf::sputsn(const char* s, int len) { for(; --len >= 0; ++s) { if (must_overflow(*s)) { if (overflow(*s) == EOF) return EOF; } else *pptr++ = *s; } return 0; } int streambuf::is_open() { return 1; } int streambuf::close() { return 1; } void streambuf::error() { abort(); } streambuf* streambuf::open(const char*, open_mode) { return 0; } streambuf* streambuf::open(const char*, io_mode, access_mode) { return 0; } streambuf* streambuf::open(const char*, const char*) { return 0; } streambuf* streambuf::open(int, io_mode) { return 0; } streambuf* streambuf::open(FILE*) { return 0; } == EOF) return EOF; } else *pptr++ = *s; } return 0; } int streambuf::is_open() { return 1; } int streambuf::close() { return 1; } void streambuf::error() { abort(); } streambuf* streambuf::open(const char*, open_mode) { return 0; } streambuf* streambuf::open(const char*, io_mode, access_mode) { return 0; } streambuf* streambuf::open(const char*, const char*) { return 0; } streambuf* streambuf::open(int, io_mode) { return 0; } strelibg++/src/GetOpt.cc 600 473 0 17646 4677700051 7462 /* Getopt for GNU. Copyright (C) 1987, 1989 Free Software Foundation, Inc. (Modified by Douglas C. Schmidt for use with GNU G++.) 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 1, 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. */ #include GetOpt::GetOpt (int argc, char **argv, char *optstring): opterr (1) { /* 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. */ nargc = argc; nargv = argv; noptstring = optstring; first_nonopt = last_nonopt = optind = 1; optarg = nextchar = 0; /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') ordering = RETURN_IN_ORDER; else if (getenv ("_POSIX_OPTION_ORDER") != 0) ordering = REQUIRE_ORDER; else ordering = PERMUTE; } void GetOpt::exchange (char **argv) { int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); char **temp = (char **) alloca (nonopts_size); /* Interchange the two blocks of data in argv. */ bcopy (&argv[first_nonopt], temp, nonopts_size); bcopy (&argv[last_nonopt], &argv[first_nonopt], (optind - last_nonopt) * sizeof (char *)); bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size); /* 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 theoption 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. A colon in OPTSTRING means that the previous character is an option that wants an argument. The argument is taken from the rest of the current ARGV-element, or from the following ARGV-element, and returned in `optarg'. 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'. If OPTSTRING starts with `-', it requests a different method of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */ int GetOpt::operator () (void) { if (nextchar == 0 || *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 (nargv); 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 < nargc && (nargv[optind][0] != '-' || nargv[optind][1] == 0)) 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 != nargc && !strcmp (nargv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange (nargv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = nargc; optind = nargc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == nargc) { /* 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 (nargv[optind][0] != '-' || nargv[optind][1] == 0) { if (ordering == REQUIRE_ORDER) return EOF; optarg = nargv[optind++]; return 0; } /* We have found another option-ARGV-element. Start decoding its characters. */ nextchar = nargv[optind] + 1; } /* Look at and handle the next option-character. */ { char c = *nextchar++; char *temp = (char *) index (noptstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == 0) optind++; if (temp == 0 || c == ':') { if (opterr != 0) { if (c < 040 || c >= 0177) fprintf (stderr, "%s: unrecognized option, character code 0%o\n", nargv[0], c); else fprintf (stderr, "%s: unrecognized option `-%c'\n", nargv[0], 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 = 0; } 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 == nargc) { if (opterr != 0) fprintf (stderr, "%s: no argument for `-%c' option\n", nargv[0], c); c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = nargv[optind++]; nextchar = 0; } } return c; } } } else if (optind == nargc) { if (optlibg++/src/regex.cc 644 473 0 137670 4677700052 7423 /* Extended regular expression matching and search. Copyright (C) 1985 Free Software Foundation, Inc. NO WARRANTY BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS 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. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. GENERAL PUBLIC LICENSE TO COPY 1. You may copy and distribute verbatim copies of this source file as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright notice "Copyright (C) 1985 Free Software Foundation, Inc."; and include following the copyright notice a verbatim copy of the above disclaimer of warranty and of this License. You may charge a distribution fee for the physical act of transferring a copy. 2. You may modify your copy or copies of this source file or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains or is a derivative of this program or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third parties, at your option). c) You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms. 3. You may copy and distribute this program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs. 4. You may not copy, sublicense, distribute or transfer this program except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer this program is void and your rights to use the program under this License agreement shall be automatically terminated. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated so long as such parties remain in full compliance. 5. If you wish to incorporate parts of this program into other free programs whose distribution conditions are different, write to the Free Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We 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. 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! */ /* To test, compile with -Dtest. This Dtestable feature turns this into a self-contained program which reads a pattern, describes how it compiles, then reads a string and searches for it. */ #ifdef emacs /* The `emacs' switch turns on certain special matching commands that make sense only in emacs. */ #include "config.h" #include "lisp.h" #include "buffer.h" #include "syntax.h" #else /* not emacs */ #include #include /* * Define the syntax stuff, so we can do the \<...\> things. */ #ifndef Sword /* must be non-zero in some of the tests below... */ #define Sword 1 #endif #define SYNTAX(c) re_syntax_table[c] #ifdef SYNTAX_TABLE char *re_syntax_table; #else static char re_syntax_table[256]; static void init_syntax_once (void) { register int c; static int done = 0; if (done) return; bzero (re_syntax_table, sizeof re_syntax_table); for (c = 'a'; c <= 'z'; c++) re_syntax_table[c] = Sword; for (c = 'A'; c <= 'Z'; c++) re_syntax_table[c] = Sword; for (c = '0'; c <= '9'; c++) re_syntax_table[c] = Sword; done = 1; } #endif /* SYNTAX_TABLE */ #endif /* not emacs */ #include "regex.h" /* Make alloca work the best possible way. */ #ifndef alloca #ifdef __GNUC__ #define alloca __builtin_alloca #else #ifdef sparc #include #endif #endif #endif /* Number of failure points to allocate space for initially, when matching. If this number is exceeded, more space is allocated, so it is not a hard limit. */ #ifndef NFAILURES #define NFAILURES 80 #endif /* NFAILURES */ /* width of a byte in bits */ #define BYTEWIDTH 8 #ifndef SIGN_EXTEND_CHAR #define SIGN_EXTEND_CHAR(x) (x) #endif static int obscure_syntax = 0; /* Specify the precise syntax of regexp for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit-mask containing the two bits RE_NO_BK_PARENS and RE_NO_BK_VBAR. */ int re_set_syntax (int syntax) { int ret; ret = obscure_syntax; obscure_syntax = syntax; return ret; } /* re_compile_pattern takes a regular-expression string and converts it into a buffer full of byte commands for matching. PATTERN is the address of the pattern string SIZE is the length of it. BUFP is a struct re_pattern_buffer * which points to the info on where to store the byte commands. This structure contains a char * which points to the actual space, which should have been obtained with malloc. re_compile_pattern may use realloc to grow the buffer space. The number of bytes of commands can be found out by looking in the struct re_pattern_buffer that bufp pointed to, after re_compile_pattern returns. */ #define PATPUSH(ch) (*b++ = (char) (ch)) #define PATFETCH(c) \ {if (p == pend) goto end_of_pattern; \ c = * (unsigned char *) p++; \ if (translate) c = translate[c]; } #define PATFETCH_RAW(c) \ {if (p == pend) goto end_of_pattern; \ c = * (unsigned char *) p++; } #define PATUNFETCH p-- #define EXTEND_BUFFER \ { char *old_buffer = bufp->buffer; \ if (bufp->allocated == (1<<16)) goto too_big; \ bufp->allocated *= 2; \ if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \ if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \ goto memory_exhausted; \ c = bufp->buffer - old_buffer; \ b += c; \ if (fixup_jump) \ fixup_jump += c; \ if (laststart) \ laststart += c; \ begalt += c; \ if (pending_exact) \ pending_exact += c; \ } static void store_jump (char *, char, char *); static void insert_jump (char, char *, char *, char *); int re_match_2 (struct re_pattern_buffer *, unsigned char *, int, unsigned char *, int, int, struct re_registers *, int mstop); char * re_compile_pattern (char *pattern, int size, struct re_pattern_buffer *bufp) { register char *b = bufp->buffer; register char *p = pattern; char *pend = pattern + size; register unsigned c, c1; char *p1; unsigned char *translate = (unsigned char *) bufp->translate; /* address of the count-byte of the most recently inserted "exactn" command. This makes it possible to tell whether a new exact-match character can be added to that command or requires a new "exactn" command. */ char *pending_exact = 0; /* address of the place where a forward-jump should go to the end of the containing expression. Each alternative of an "or", except the last, ends with a forward-jump of this sort. */ char *fixup_jump = 0; /* address of start of the most recently finished expression. This tells postfix * where to find the start of its operand. */ char *laststart = 0; /* In processing a repeat, 1 means zero matches is allowed */ char zero_times_ok; /* In processing a repeat, 1 means many matches is allowed */ char many_times_ok; /* address of beginning of regexp, or inside of last \( */ char *begalt = b; /* Stack of information saved by \( and restored by \). Four stack elements are pushed by each \(: First, the value of b. Second, the value of fixup_jump. Third, the value of regnum. Fourth, the value of begalt. */ int stackb[40]; int *stackp = stackb; int *stacke = stackb + 40; int *stackt; /* Counts \('s as they are encountered. Remembered for the matching \), where it becomes the "register number" to put in the stop_memory command */ int regnum = 1; bufp->fastmap_accurate = 0; #ifndef emacs #ifndef SYNTAX_TABLE /* * Initialize the syntax table. */ init_syntax_once(); #endif #endif if (bufp->allocated == 0) { bufp->allocated = 28; if (bufp->buffer) /* EXTEND_BUFFER loses when bufp->allocated is 0 */ bufp->buffer = (char *) realloc (bufp->buffer, 28); else /* Caller did not allocate a buffer. Do it for him */ bufp->buffer = (char *) new char[28]; if (!bufp->buffer) goto memory_exhausted; begalt = b = bufp->buffer; } while (p != pend) { if (b - bufp->buffer > bufp->allocated - 10) /* Note that EXTEND_BUFFER clobbers c */ EXTEND_BUFFER; PATFETCH (c); switch (c) { case '$': if (obscure_syntax & RE_TIGHT_VBAR) { if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend) goto normal_char; /* Make operand of last vbar end before this `$'. */ if (fixup_jump) store_jump (fixup_jump, jump, b); fixup_jump = 0; PATPUSH (endline); break; } /* $ means succeed if at end of line, but only in special contexts. If randomly in the middle of a pattern, it is a normal character. */ if (p == pend || *p == '\n' || (obscure_syntax & RE_CONTEXT_INDEP_OPS) || (obscure_syntax & RE_NO_BK_PARENS ? *p == ')' : *p == '\\' && p[1] == ')') || (obscure_syntax & RE_NO_BK_VBAR ? *p == '|' : *p == '\\' && p[1] == '|')) { PATPUSH (endline); break; } goto normal_char; case '^': /* ^ means succeed if at beg of line, but only if no preceding pattern. */ if (laststart && p[-2] != '\n' && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; if (obscure_syntax & RE_TIGHT_VBAR) { if (p != pattern + 1 && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; PATPUSH (begline); begalt = b; } else PATPUSH (begline); break; case '+': case '?': if (obscure_syntax & RE_BK_PLUS_QM) goto normal_char; handle_plus: case '*': /* If there is no previous pattern, char not special. */ if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; /* If there is a sequence of repetition chars, collapse it down to equivalent to just one. */ zero_times_ok = 0; many_times_ok = 0; while (1) { zero_times_ok |= c != '+'; many_times_ok |= c != '?'; if (p == pend) break; PATFETCH (c); if (c == '*') ; else if (!(obscure_syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')) ; else if ((obscure_syntax & RE_BK_PLUS_QM) && c == '\\') { int c1; PATFETCH (c1); if (!(c1 == '+' || c1 == '?')) { PATUNFETCH; PATUNFETCH; break; } c = c1; } else { PATUNFETCH; break; } } /* Star, etc. applied to an empty pattern is equivalent to an empty pattern. */ if (!laststart) break; /* Now we know whether 0 matches is allowed, and whether 2 or more matches is allowed. */ if (many_times_ok) { /* If more than one repetition is allowed, put in a backward jump at the end. */ store_jump (b, maybe_finalize_jump, laststart - 3); b += 3; } insert_jump (on_failure_jump, laststart, b + 3, b); pending_exact = 0; b += 3; if (!zero_times_ok) { /* At least one repetition required: insert before the loop a skip over the initial on-failure-jump instruction */ insert_jump (dummy_failure_jump, laststart, laststart + 6, b); b += 3; } break; case '.': laststart = b; PATPUSH (anychar); break; case '[': while (b - bufp->buffer > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH) /* Note that EXTEND_BUFFER clobbers c */ EXTEND_BUFFER; laststart = b; if (*p == '^') PATPUSH (charset_not), p++; else PATPUSH (charset); p1 = p; PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH); /* Clear the whole map */ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); /* Read in characters and ranges, setting map bits */ while (1) { PATFETCH (c); if (c == ']' && p != p1 + 1) break; if (*p == '-' && p[1] != ']') { PATFETCH (c1); PATFETCH (c1); while (c <= c1) b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++; } else { b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH); } } /* Discard any bitmap bytes that are all 0 at the end of the map. Decrement the map-length byte too. */ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; b += b[-1]; break; case '(': if (! (obscure_syntax & RE_NO_BK_PARENS)) goto normal_char; else goto handle_open; case ')': if (! (obscure_syntax & RE_NO_BK_PARENS)) goto normal_char; else goto handle_close; case '\n': if (! (obscure_syntax & RE_NEWLINE_OR)) goto normal_char; else goto handle_bar; case '|': if (! (obscure_syntax & RE_NO_BK_VBAR)) goto normal_char; else goto handle_bar; case '\\': if (p == pend) goto invalid_pattern; PATFETCH_RAW (c); switch (c) { case '(': if (obscure_syntax & RE_NO_BK_PARENS) goto normal_backsl; handle_open: if (stackp == stacke) goto nesting_too_deep; if (regnum < RE_NREGS) { PATPUSH (start_memory); PATPUSH (regnum); } *stackp++ = b - bufp->buffer; *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; *stackp++ = regnum++; *stackp++ = begalt - bufp->buffer; fixup_jump = 0; laststart = 0; begalt = b; break; case ')': if (obscure_syntax & RE_NO_BK_PARENS) goto normal_backsl; handle_close: if (stackp == stackb) goto unmatched_close; begalt = *--stackp + bufp->buffer; if (fixup_jump) store_jump (fixup_jump, jump, b); if (stackp[-1] < RE_NREGS) { PATPUSH (stop_memory); PATPUSH (stackp[-1]); } stackp -= 2; fixup_jump = 0; if (*stackp) fixup_jump = *stackp + bufp->buffer - 1; laststart = *--stackp + bufp->buffer; break; case '|': if (obscure_syntax & RE_NO_BK_VBAR) goto normal_backsl; handle_bar: insert_jump (on_failure_jump, begalt, b + 6, b); pending_exact = 0; b += 3; if (fixup_jump) store_jump (fixup_jump, jump, b); fixup_jump = b; b += 3; laststart = 0; begalt = b; break; #ifdef emacs case '=': PATPUSH (at_dot); break; case 's': laststart = b; PATPUSH (syntaxspec); PATFETCH (c); PATPUSH (syntax_spec_code[c]); break; case 'S': laststart = b; PATPUSH (notsyntaxspec); PATFETCH (c); PATPUSH (syntax_spec_code[c]); break; #endif /* emacs */ case 'w': laststart = b; PATPUSH (wordchar); break; case 'W': laststart = b; PATPUSH (notwordchar); break; case '<': PATPUSH (wordbeg); break; case '>': PATPUSH (wordend); break; case 'b': PATPUSH (wordbound); break; case 'B': PATPUSH (notwordbound); break; case '`': PATPUSH (begbuf); break; case '\'': PATPUSH (endbuf); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c1 = c - '0'; if (c1 >= regnum) goto normal_char; for (stackt = stackp - 2; stackt > stackb; stackt -= 4) if (*stackt == c1) goto normal_char; laststart = b; PATPUSH (duplicate); PATPUSH (c1); break; case '+': case '?': if (obscure_syntax & RE_BK_PLUS_QM) goto handle_plus; default: normal_backsl: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ if (translate) c = translate[c]; goto normal_char; } break; default: normal_char: if (!pending_exact || pending_exact + *pending_exact + 1 != b || *pending_exact == 0177 || *p == '*' || *p == '^' || ((obscure_syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') : (*p == '+' || *p == '?'))) { laststart = b; PATPUSH (exactn); pending_exact = b; PATPUSH (0); } PATPUSH (c); (*pending_exact)++; } } if (fixup_jump) store_jump (fixup_jump, jump, b); if (stackp != stackb) goto unmatched_open; bufp->used = b - bufp->buffer; return 0; invalid_pattern: return "Invalid regular expression"; unmatched_open: return "Unmatched \\("; unmatched_close: return "Unmatched \\)"; end_of_pattern: return "Premature end of regular expression"; nesting_too_deep: return "Nesting too deep"; too_big: return "Regular expression too big"; memory_exhausted: return "Memory exhausted"; } /* Store where `from' points a jump operation to jump to where `to' points. `opcode' is the opcode to store. */ static void store_jump (char *from, char opcode, char *to) { from[0] = opcode; from[1] = (to - (from + 3)) & 0377; from[2] = (to - (from + 3)) >> 8; } /* Open up space at char FROM, and insert there a jump to TO. CURRENT_END gives te end of the storage no in use, so we know how much data to copy up. OP is the opcode of the jump to insert. If you call this function, you must zero out pending_exact. */ static void insert_jump (char op, char *from, char *to, char *current_end) { register char *pto = current_end + 3; register char *pfrom = current_end; while (pfrom != from) *--pto = *--pfrom; store_jump (from, op, to); } /* Given a pattern, compute a fastmap from it. The fastmap records which of the (1 << BYTEWIDTH) possible characters can start a string that matches the pattern. This fastmap is used by re_search to skip quickly over totally implausible text. The caller must supply the address of a (1 << BYTEWIDTH)-byte data area as bufp->fastmap. The other components of bufp describe the pattern to be used. */ void re_compile_fastmap (struct re_pattern_buffer *bufp) { unsigned char *pattern = (unsigned char *) bufp->buffer; int size = bufp->used; register char *fastmap = bufp->fastmap; register unsigned char *p = pattern; register unsigned char *pend = pattern + size; register int j; unsigned char *translate = (unsigned char *) bufp->translate; unsigned char *stackb[NFAILURES]; unsigned char **stackp = stackb; bzero (fastmap, (1 << BYTEWIDTH)); bufp->fastmap_accurate = 1; bufp->can_be_null = 0; while (p) { if (p == pend) { bufp->can_be_null = 1; break; } #ifdef SWITCH_ENUM_BUG switch ((int) ((enum regexpcode) *p++)) #else switch ((enum regexpcode) *p++) #endif { case exactn: if (translate) fastmap[translate[p[1]]] = 1; else fastmap[p[1]] = 1; break; case begline: case before_dot: case at_dot: case after_dot: case begbuf: case endbuf: case wordbound: case notwordbound: case wordbeg: case wordend: continue; case endline: if (translate) fastmap[translate['\n']] = 1; else fastmap['\n'] = 1; if (bufp->can_be_null != 1) bufp->can_be_null = 2; break; case finalize_jump: case maybe_finalize_jump: case jump: case dummy_failure_jump: bufp->can_be_null = 1; j = *p++ & 0377; j += SIGN_EXTEND_CHAR (*(char *)p) << 8; p += j + 1; /* The 1 compensates for missing ++ above */ if (j > 0) continue; /* Jump backward reached implies we just went through the body of a loop and matched nothing. Opcode jumped to should be an on_failure_jump. Just treat it like an ordinary jump. For a * loop, it has pushed its failure point already; if so, discard that as redundant. */ if ((enum regexpcode) *p != on_failure_jump) continue; p++; j = *p++ & 0377; j += SIGN_EXTEND_CHAR (*(char *)p) << 8; p += j + 1; /* The 1 compensates for missing ++ above */ if (stackp != stackb && *stackp == p) stackp--; continue; case on_failure_jump: j = *p++ & 0377; j += SIGN_EXTEND_CHAR (*(char *)p) << 8; p++; *++stackp = p + j; continue; case start_memory: case stop_memory: p++; continue; case duplicate: bufp->can_be_null = 1; fastmap['\n'] = 1; case anychar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (j != '\n') fastmap[j] = 1; if (bufp->can_be_null) return; /* Don't return; check the alternative paths so we can set can_be_null if appropriate. */ break; case wordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == Sword) fastmap[j] = 1; break; case notwordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != Sword) fastmap[j] = 1; break; #ifdef emacs case syntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == (enum syntaxcode) k) fastmap[j] = 1; break; case notsyntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != (enum syntaxcode) k) fastmap[j] = 1; break; #endif /* emacs */ case charset: for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) { if (translate) fastmap[translate[j]] = 1; else fastmap[j] = 1; } break; case charset_not: /* Chars beyond end of map must be allowed */ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) if (translate) fastmap[translate[j]] = 1; else fastmap[j] = 1; for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) { if (translate) fastmap[translate[j]] = 1; else fastmap[j] = 1; } break; } /* Get here means we have successfully found the possible starting characters of one path of the pattern. We need not follow this path any farther. Instead, look at the next alternative remembered in the stack. */ if (stackp != stackb) p = *stackp--; else break; } } /* Like re_search_2, below, but only one string is specified. */ int re_search (struct re_pattern_buffer *pbufp, char *string, int size, int startpos, int range, struct re_registers *regs) { return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size); } /* Like re_match_2 but tries first a match starting at index STARTPOS, then at STARTPOS + 1, and so on. RANGE is the number of places to try before giving up. If RANGE is negative, the starting positions tried are STARTPOS, STARTPOS - 1, etc. It is up to the caller to make sure that range is not so large as to take the starting position outside of the input strings. The value returned is the position at which the match was found, or -1 if no match was found, or -2 if error (such as failure stack overflow). */ int re_search_2 (struct re_pattern_buffer *pbufp, char *string1, int size1, char *string2, int size2, int startpos, register int range, struct re_registers *regs, int mstop) { register char *fastmap = pbufp->fastmap; register unsigned char *translate = (unsigned char *) pbufp->translate; int total = size1 + size2; int val; /* Update the fastmap now if not correct already */ if (fastmap && !pbufp->fastmap_accurate) re_compile_fastmap (pbufp); /* Don't waste time in a long search for a pattern that says it is anchored. */ if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf && range > 0) { if (startpos > 0) return -1; else range = 1; } while (1) { /* If a fastmap is supplied, skip quickly over characters that cannot possibly be the start of a match. Note, however, that if the pattern can possibly match the null string, we must test it at each starting point so that we take the first null string we get. */ if (fastmap && startpos < total && pbufp->can_be_null != 1) { if (range > 0) { register int lim = 0; register unsigned char *p; int irange = range; if (startpos < size1 && startpos + range >= size1) lim = range - (size1 - startpos); p = ((unsigned char *) &(startpos >= size1 ? string2 - size1 : string1)[startpos]); if (translate) { while (range > lim && !fastmap[translate[*p++]]) range--; } else { while (range > lim && !fastmap[*p++]) range--; } startpos += irange - range; } else { register unsigned char c; if (startpos >= size1) c = string2[startpos - size1]; else c = string1[startpos]; c &= 0xff; if (translate ? !fastmap[translate[c]] : !fastmap[c]) goto advance; } } if (range >= 0 && startpos == total && fastmap && pbufp->can_be_null == 0) return -1; val = re_match_2 (pbufp, (unsigned char *) string1, size1, (unsigned char *) string2, size2, startpos, regs, mstop); if (0 <= val) { if (val == -2) return -2; return startpos; } #ifdef C_ALLOCA alloca (0); #endif /* C_ALLOCA */ advance: if (!range) break; if (range > 0) range--, startpos++; else range++, startpos--; } return -1; } #ifndef emacs /* emacs never uses this */ int re_match (struct re_pattern_buffer *pbufp, char *string, int size, int pos, struct re_registers *regs) { return re_match_2 (pbufp, (unsigned char *) 0, 0, (unsigned char *) string, size, pos, regs, size); } #endif /* emacs */ /* Maximum size of failure stack. Beyond this, overflow is an error. */ int re_max_failures = 2000; static int bcmp_translate(unsigned char *, unsigned char *, int, unsigned char *); /* Match the pattern described by PBUFP against data which is the virtual concatenation of STRING1 and STRING2. SIZE1 and SIZE2 are the sizes of the two data strings. Start the match at position POS. Do not consider matching past the position MSTOP. If pbufp->fastmap is nonzero, then it had better be up to date. The reason that the data to match are specified as two components which are to be regarded as concatenated is so this function can be used directly on the contents of an Emacs buffer. -1 is returned if there is no match. -2 is returned if there is an error (such as match stack overflow). Otherwise the value is the length of the substring which was matched. */ int re_match_2 (struct re_pattern_buffer *pbufp, unsigned char *string1, int size1, unsigned char *string2, int size2, int pos, struct re_registers *regs, int mstop) { register unsigned char *p = (unsigned char *) pbufp->buffer; register unsigned char *pend = p + pbufp->used; /* End of first string */ unsigned char *end1; /* End of second string */ unsigned char *end2; /* Pointer just past last char to consider matching */ unsigned char *end_match_1, *end_match_2; register unsigned char *d, *dend; register int mcnt; unsigned char *translate = (unsigned char *) pbufp->translate; /* Failure point stack. Each place that can handle a failure further down the line pushes a failure point on this stack. It consists of two char *'s. The first one pushed is where to resume scanning the pattern; the second pushed is where to resume scanning the strings. If the latter is zero, the failure point is a "dummy". If a failure happens and the innermost failure point is dormant, it discards that failure point and tries the next one. */ unsigned char *initial_stack[2 * NFAILURES]; unsigned char **stackb = initial_stack; unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES]; /* Information on the "contents" of registers. These are pointers into the input strings; they record just what was matched (on this attempt) by some part of the pattern. The start_memory command stores the start of a register's contents and the stop_memory command stores the end. At that point, regstart[regnum] points to the first character in the register, regend[regnum] points to the first character beyond the end of the register, regstart_seg1[regnum] is true iff regstart[regnum] points into string1, and regend_seg1[regnum] is true iff regend[regnum] points into string1. */ unsigned char *regstart[RE_NREGS]; unsigned char *regend[RE_NREGS]; unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS]; /* Set up pointers to ends of strings. Don't allow the second string to be empty unless both are empty. */ if (!size2) { string2 = string1; size2 = size1; string1 = 0; size1 = 0; } end1 = string1 + size1; end2 = string2 + size2; /* Compute where to stop matching, within the two strings */ if (mstop <= size1) { end_match_1 = string1 + mstop; end_match_2 = string2; } else { end_match_1 = end1; end_match_2 = string2 + mstop - size1; } /* Initialize \) text positions to -1 to mark ones that no \( or \) has been seen for. */ for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++) regend[mcnt] = (unsigned char *) -1; /* `p' scans through the pattern as `d' scans through the data. `dend' is the end of the input string that `d' points within. `d' is advanced into the following input string whenever necessary, but this happens before fetching; therefore, at the beginning of the loop, `d' can be pointing at the end of a string, but it cannot equal string2. */ if (pos <= size1) d = string1 + pos, dend = end_match_1; else d = string2 + pos - size1, dend = end_match_2; /* Write PREFETCH; just before fetching a character with *d. */ #define PREFETCH \ while (d == dend) \ { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \ d = string2; /* end of string1 => advance to string2. */ \ dend = end_match_2; } /* This loop loops over pattern commands. It exits by returning from the function if match is complete, or it drops through if match fails at this starting point in the input data. */ while (1) { if (p == pend) /* End of pattern means we have succeeded! */ { /* If caller wants register contents data back, convert it to indices */ if (regs) { regs->start[0] = pos; if (dend == end_match_1) regs->end[0] = d - string1; else regs->end[0] = d - string2 + size1; for (mcnt = 1; mcnt < RE_NREGS; mcnt++) { if (regend[mcnt] == (unsigned char *) -1) { regs->start[mcnt] = -1; regs->end[mcnt] = -1; continue; } if (regstart_seg1[mcnt]) regs->start[mcnt] = regstart[mcnt] - string1; else regs->start[mcnt] = regstart[mcnt] - string2 + size1; if (regend_seg1[mcnt]) regs->end[mcnt] = regend[mcnt] - string1; else regs->end[mcnt] = regend[mcnt] - string2 + size1; } } if (dend == end_match_1) return (d - string1 - pos); else return d - string2 + size1 - pos; } /* Otherwise match next pattern command */ #ifdef SWITCH_ENUM_BUG switch ((int) ((enum regexpcode) *p++)) #else switch ((enum regexpcode) *p++) #endif { /* \( is represented by a start_memory, \) by a stop_memory. Both of those commands contain a "register number" argument. The text matched within the \( and \) is recorded under that number. Then, \ turns into a `duplicate' command which is followed by the numeric value of as the register number. */ case start_memory: regstart[*p] = d; regstart_seg1[*p++] = (dend == end_match_1); break; case stop_memory: regend[*p] = d; regend_seg1[*p++] = (dend == end_match_1); break; case duplicate: { int regno = *p++; /* Get which register to match against */ register unsigned char *d2, *dend2; d2 = regstart[regno]; dend2 = ((regstart_seg1[regno] == regend_seg1[regno]) ? regend[regno] : end_match_1); while (1) { /* Advance to next segment in register contents, if necessary */ while (d2 == dend2) { if (dend2 == end_match_2) break; if (dend2 == regend[regno]) break; d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */ } /* At end of register contents => success */ if (d2 == dend2) break; /* Advance to next segment in data being matched, if necessary */ PREFETCH; /* mcnt gets # consecutive chars to compare */ mcnt = dend - d; if (mcnt > dend2 - d2) mcnt = dend2 - d2; /* Compare that many; failure if mismatch, else skip them. */ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt)) goto fail; d += mcnt, d2 += mcnt; } } break; case anychar: /* fetch a data character */ PREFETCH; /* Match anything but a newline. */ if ((translate ? translate[*d++] : *d++) == '\n') goto fail; break; case charset: case charset_not: { /* Nonzero for charset_not */ int not = 0; register int c; if (*(p - 1) == (unsigned char) charset_not) not = 1; /* fetch a data character */ PREFETCH; if (translate) c = translate [*d]; else c = *d; if (c < *p * BYTEWIDTH && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; p += 1 + *p; if (!not) goto fail; d++; break; } case begline: if (d == string1 || d[-1] == '\n') break; goto fail; case endline: if (d == end2 || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n')) break; goto fail; /* "or" constructs ("|") are handled by starting each alternative with an on_failure_jump that points to the start of the next alternative. Each alternative except the last ends with a jump to the joining point. (Actually, each jump except for the last one really jumps to the following jump, because tensioning the jumps is a hassle.) */ /* The start of a stupid repeat has an on_failure_jump that points past the end of the repeat text. This makes a failure point so that, on failure to match a repetition, matching restarts past as many repetitions have been found with no way to fail and look for another one. */ /* A smart repeat is similar but loops back to the on_failure_jump so that each repetition makes another failure point. */ case on_failure_jump: if (stackp == stacke) { unsigned char **stackx; if (stacke - stackb > re_max_failures * 2) return -2; stackx = (unsigned char **) alloca (2 * (stacke - stackb) * sizeof (char *)); bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *)); stackp = stackx + (stackp - stackb); stacke = stackx + 2 * (stacke - stackb); stackb = stackx; } mcnt = *p++ & 0377; mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; p++; *stackp++ = mcnt + p; *stackp++ = d; break; /* The end of a smart repeat has an maybe_finalize_jump back. Change it either to a finalize_jump or an ordinary jump. */ case maybe_finalize_jump: mcnt = *p++ & 0377; mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; p++; { register unsigned char *p2 = p; /* Compare what follows with the begining of the repeat. If we can establish that there is nothing that they would both match, we can change to finalize_jump */ while (p2 != pend && (*p2 == (unsigned char) stop_memory || *p2 == (unsigned char) start_memory)) p2++; if (p2 == pend) p[-3] = (unsigned char) finalize_jump; else if (*p2 == (unsigned char) exactn || *p2 == (unsigned char) endline) { register int c = *p2 == (unsigned char) endline ? '\n' : p2[2]; register unsigned char *p1 = p + mcnt; /* p1[0] ... p1[2] are an on_failure_jump. Examine what follows that */ if (p1[3] == (unsigned char) exactn && p1[5] != c) p[-3] = (unsigned char) finalize_jump; else if (p1[3] == (unsigned char) charset || p1[3] == (unsigned char) charset_not) { int not = p1[3] == (unsigned char) charset_not; if (c < p1[4] * BYTEWIDTH && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; /* not is 1 if c would match */ /* That means it is not safe to finalize */ if (!not) p[-3] = (unsigned char) finalize_jump; } } } p -= 2; if (p[-1] != (unsigned char) finalize_jump) { p[-1] = (unsigned char) jump; goto nofinalize; } /* The end of a stupid repeat has a finalize-jump back to the start, where another failure point will be made which will point after all the repetitions found so far. */ case finalize_jump: stackp -= 2; case jump: nofinalize: mcnt = *p++ & 0377; mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; p += mcnt + 1; /* The 1 compensates for missing ++ above */ break; case dummy_failure_jump: if (stackp == stacke) { unsigned char **stackx = (unsigned char **) alloca (2 * (stacke - stackb) * sizeof (char *)); bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *)); stackp = stackx + (stackp - stackb); stacke = stackx + 2 * (stacke - stackb); stackb = stackx; } *stackp++ = 0; *stackp++ = 0; goto nofinalize; case wordbound: if (d == string1 /* Points to first char */ || d == end2 /* Points to end */ || (d == end1 && size2 == 0)) /* Points to end */ break; if ((SYNTAX (d[-1]) == Sword) != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) break; goto fail; case notwordbound: if (d == string1 /* Points to first char */ || d == end2 /* Points to end */ || (d == end1 && size2 == 0)) /* Points to end */ goto fail; if ((SYNTAX (d[-1]) == Sword) != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) goto fail; break; case wordbeg: if (d == end2 /* Points to end */ || (d == end1 && size2 == 0) /* Points to end */ || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */ goto fail; if (d == string1 /* Points to first char */ || SYNTAX (d[-1]) != Sword) /* prev char not letter */ break; goto fail; case wordend: if (d == string1 /* Points to first char */ || SYNTAX (d[-1]) != Sword) /* prev char not letter */ goto fail; if (d == end2 /* Points to end */ || (d == end1 && size2 == 0) /* Points to end */ || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */ break; goto fail; #ifdef emacs case before_dot: if (((d - string2 <= (unsigned) size2) ? d - bf_p2 : d - bf_p1) <= point) goto fail; break; case at_dot: if (((d - string2 <= (unsigned) size2) ? d - bf_p2 : d - bf_p1) == point) goto fail; break; case after_dot: if (((d - string2 <= (unsigned) size2) ? d - bf_p2 : d - bf_p1) >= point) goto fail; break; case wordchar: mcnt = (int) Sword; goto matchsyntax; case syntaxspec: mcnt = *p++; matchsyntax: PREFETCH; if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; break; case notwordchar: mcnt = (int) Sword; goto matchnotsyntax; case notsyntaxspec: mcnt = *p++; matchnotsyntax: PREFETCH; if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; break; #else case wordchar: PREFETCH; if (SYNTAX (*d++) == 0) goto fail; break; case notwordchar: PREFETCH; if (SYNTAX (*d++) != 0) goto fail; break; #endif /* not emacs */ case begbuf: if (d == string1) /* Note, d cannot equal string2 */ break; /* unless string1 == string2. */ goto fail; case endbuf: if (d == end2 || (d == end1 && size2 == 0)) break; goto fail; case exactn: /* Match the next few pattern characters exactly. mcnt is how many characters to match. */ mcnt = *p++; if (translate) { do { PREFETCH; if (translate[*d++] != *p++) goto fail; } while (--mcnt); } else { do { PREFETCH; if (*d++ != *p++) goto fail; } while (--mcnt); } break; } continue; /* Successfully matched one pattern command; keep matching */ /* Jump here if any matching operation fails. */ fail: if (stackp != stackb) /* A restart point is known. Restart there and pop it. */ { if (!stackp[-2]) { /* If innermost failure point is dormant, flush it and keep looking */ stackp -= 2; goto fail; } d = *--stackp; p = *--stackp; if (d >= string1 && d <= end1) dend = end_match_1; } else break; /* Matching at this starting point really fails! */ } return -1; /* Failure to match */ } static int bcmp_translate (unsigned char *s1, unsigned char *s2, register int len, unsigned char *translate) { register unsigned char *p1 = s1, *p2 = s2; while (len) { if (translate [*p1++] != translate [*p2++]) return 1; len--; } return 0; } /* Entry points compatible with bsd4.2 regex library */ #ifndef emacs static struct re_pattern_buffer re_comp_buf; char * re_comp (char *s) { if (!s) { if (!re_comp_buf.buffer) return "No previous regular expression"; return 0; } if (!re_comp_buf.buffer) { if (!(re_comp_buf.buffer = (char *) new char[200])) return "Memory exhausted"; re_comp_buf.allocated = 200; if (!(re_comp_buf.fastmap = (char *) new char[ (1 << BYTEWIDTH)])) return "Memory exhausted"; } return re_compile_pattern (s, strlen (s), &re_comp_buf); } int re_exec (char *s) { int len = strlen (s); return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0); } #endif /* emacs */ #ifdef test #include /* Indexed by a character, gives the upper case equivalent of the character */ static char upcase[0400] = { 000, 001, 002, 003, 004, 005, 006, 007, 010, 011, 012, 013, 014, 015, 016, 017, 020, 021, 022, 023, 024, 025, 026, 027, 030, 031, 032, 033, 034, 035, 036, 037, 040, 041, 042, 043, 044, 045, 046, 047, 050, 051, 052, 053, 054, 055, 056, 057, 060, 061, 062, 063, 064, 065, 066, 067, 070, 071, 072, 073, 074, 075, 076, 077, 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 }; main (int argc, char **argv) { char pat[80]; struct re_pattern_buffer buf; int i; char c; char fastmap[(1 << BYTEWIDTH)]; /* Allow a command argument to specify the style of syntax. */ if (argc > 1) obscure_syntax = atoi (argv[1]); buf.allocated = 40; buf.buffer = (char *) new char[buf.allocated]; buf.fastmap = fastmap; buf.translate = upcase; while (1) { gets (pat); if (*pat) { re_compile_pattern (pat, strlen(pat), &buf); for (i = 0; i < buf.used; i++) printchar (buf.buffer[i]); putchar ('\n'); printf ("%d allocated, %d used.\n", buf.allocated, buf.used); re_compile_fastmap (&buf); printf ("Allowed by fastmap: "); for (i = 0; i < (1 << BYTEWIDTH); i++) if (fastmap[i]) printchar (i); putchar ('\n'); } gets (pat); /* Now read the string to match against */ i = re_match (&buf, pat, strlen (pat), 0, 0); printf ("Match value %d.\n", i); } } #ifdef NOTDEF print_buf (struct re_pattern_buffer *bufp) { int i; printf ("buf is :\n----------------\n"); for (i = 0; i < bufp->used; i++) printchar (bufp->buffer[i]); printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); printf ("Allowed by fastmap: "); for (i = 0; i < (1 << BYTEWIDTH); i++) if (bufp->fastmap[i]) printchar (i); printf ("\nAllowed by translate: "); if (bufp->translate) for (i = 0; i < (1 << BYTEWIDTH); i++) if (bufp->translate[i]) printchar (i); printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); } #endif printchar (char c) { if (c < 041 || c >= 0177) { putchar ('\\'); putchar (((c >> 6) & 3) + '0'); putchar (((c >> 3) & 7) + '0'); putchar ((c & 7) + '0'); } else putchar (c); } error (char *string) { puts (string); exit (1); } #endif /* test */ TEWIDTH); i++) if (bufp->translate[i]) printchar (i); printf ("libg++/src/NegExp.cc 644 473 0 2024 4677700052 7417 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double NegativeExpntl::operator()() { return(-pMean * log(pGenerator -> asDouble())); } CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double NegativeExpntl::operator()() { return(-pMean * log(pGeneratorlibg++/src/malloc.c 644 473 0 73512 4677700053 7370 /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #ifndef NO_LIBGXX_MALLOC /* ignore whole file otherwise */ /* compile with -DMALLOC_STATS to collect statistics */ /* collecting statistics slows down malloc by at least 15% */ #ifdef MALLOC_STATS #define UPDATE_STATS(ARGS) {ARGS;} #else #define UPDATE_STATS(ARGS) #endif /* History Tue Jan 16 04:54:27 1990 Doug Lea (dl at g.oswego.edu) version 1 released in libg++ Sun Jan 21 05:52:47 1990 Doug Lea (dl at g.oswego.edu) bins are now own struct for, sanity. new victim search strategy: scan up and consolidate. Both faster and less fragmentation. refined when to scan bins for consolidation, via consollink, etc. realloc: always try to expand chunk, avoiding some fragmentation. changed a few inlines into macros hardwired SBRK_UNIT to 4096 for uniformity across systems */ /* A version of malloc/free/realloc tuned for C++ applications. Here's what you probably want to know first: In various tests, this appears to be about as fast as, and usually substantially less memory-wasteful than BSD/GNUemacs malloc. Generally, it is slower (by perhaps 20%) than bsd-style malloc only when bsd malloc would waste a great deal of space in fragmented blocks, which this malloc recovers; or when, by chance or design, nearly all requests are near the bsd malloc power-of-2 allocation bin boundaries, and as many chunks are used as are allocated. It uses more space than bsd malloc only when, again by chance or design, only bsdmalloc bin-sized requests are malloced, or when little dynamic space is malloced, since this malloc may grab larger chunks from the system at a time than bsd. In other words, this malloc seems generally superior to bsd except perhaps for programs that are specially tuned to deal with bsdmalloc's characteristics. But even here, the performance differences are slight. This malloc, like any other, is a compromised design. Chunks of memory are maintained using a `boundary tag' method as described in e.g., Knuth or Standish. This means that the size of the chunk is stored both in the front of the chunk and at the end. This makes consolidating fragmented chunks into bigger chunks very fast. The size field is also used to hold bits representing whether a chunk is free or in use. Malloced chunks have space overhead of 8 bytes: The preceding and trailing size fields. When they are freed, the list pointer fields are also needed. Available chunks are kept in doubly linked lists. The lists are maintained in an array of bins using a power-of-two method, except that instead of 32 bins (one for each 1 << i), there are 128: each power of two is split in quarters. The use of very fine bin sizes closely approximates the use of one bin per actually used size, without necessitating the overhead of locating such bins. It is especially desirable in common C++ applications where large numbers of identically-sized blocks are malloced/freed in some dynamic manner, and then later are all freed. The finer bin sizes make finding blocks fast, with little wasted overallocation. The consolidation methods ensure that once the collection of blocks is no longer useful, fragments are gathered into bigger chunks awaiting new roles. The bins av[i] serve as heads of the lists. Bins contain a dummy header for the chunk lists, and a `dirty' field used to indicate whether the list may need to be scanned for consolidation. On allocation, the bin corresponding to the request size is scanned, and if there is a chunk with size >= requested, it is split, if too big, and used. If no chunk exists in the list, a bigger chunk is found. To minimize unsuccessful scanning of a large number of probably empty bins (as happens when so many bins are used), a single designated ``victim'' ibin s maintained, and is considered first. The designated victim is that holding the last remaindered or consolidated chunk. If the victim is unusable (too small), then a new victim is searched for by scanning bigger bins. If the victim is usable, it is split. The remainder is placed on the back of the appropriate bin list. (All freed chunks are placed on fronts of lists. All remaindered or consolidated chunks are placed on the rear. Correspondingly, searching within a bin starts at the front, but finding victims is from the back. All of this approximates the effect of having 2 kinds of lists per bin: returned chunks vs unallocated chunks, but without the overhead of maintaining 2 lists.) If no victim can be found, then smaller bins are examined for consolidation. Finally, if consolidation fails to come up with a usable chunk, more space is obtained from the system. Deallocation (free) consists only of placing the chunk on a list. Reallocation proceeds in the usual way. If a chunk can be extended, it is, else a malloc-copy-free sequence is taken. Some other implementation matters: 8 byte alignment is currently hardwired into the design. The basic overhead of a used chunk is 8 bytes: 4 at the front and 4 at the end. When a chunk is free, 8 additional bytes are needed for free list pointers. Thus, the minimum allocatable size is 16 bytes. The existence of front and back overhead permits some reasonably effective fence-bashing checks: The front and back fields must be identical. This is checked only within free() and realloc(). The checks are fast enough to be made non-optional. The overwriting of parts of freed memory with the freelist pointers can also be very effective (albeit in an annoying way) in helping users track down dangling pointers. User overwriting of freed space will often result in crashes within malloc or free. These routines are also tuned to C++ in that free(0) is a noop and a failed malloc automatically calls (*new_handler)(). malloc(0) returns a pointer to something of the minimum allocatable size. Additional memory is gathered from the system (via sbrk) in a way that allows chunks obtained across different sbrk calls to be consolidated, but does not require contiguous memory: Thus, it should be safe to intersperse mallocs with other sbrk calls. This malloc is NOT designed to work in multiprocessing applications. No semaphores or other concurrency control are provided to ensure that multiple malloc or free calls don't run at the same time, which could be disasterous. VERY heavy use of inlines is made, for clarity. If this malloc is ported via a compiler without inlining capabilities, all inlines should be transformed into macros -- making them non-inline makes malloc at least twice as slow. */ /* preliminaries */ #ifdef __cplusplus #include #else #include "//usr/include/stdio.h" /* needed for error reporting */ #endif #ifdef __cplusplus extern "C" { #endif #ifdef USG extern void* memset(void*, int, int); extern void* memcpy(void*, const void*, int); inline void bzero(void* s, int l) { memset(s, 0, l); } inline void bcopy(const void* s, void* d, int l) { memcpy(d, s, l); } #else extern void bcopy(void*, void*, unsigned int); extern void bzero(void*, unsigned int); #endif extern void* sbrk(unsigned int); #ifndef __cplusplus extern int fputs(const char*, FILE*); extern int fprintf(FILE*, const char*, ...); #endif #ifdef __GNUC__ extern volatile void abort(); #else extern void abort(); #endif #ifdef __cplusplus }; /* end of extern "C" */ #endif /* A good multiple to call sbrk with */ #define SBRK_UNIT 4096 /* how to die on detected error */ #ifdef __GNUC__ static volatile void malloc_user_error() #else static void malloc_user_error() #endif { fputs("malloc/free/realloc: clobbered space detected\n", stderr); abort(); } /* Basic overhead for each malloc'ed chunk */ struct malloc_chunk { unsigned int size; /* Size in bytes, including overhead. */ /* Or'ed with INUSE if in use. */ struct malloc_chunk* fd; /* double links -- used only if free. */ struct malloc_chunk* bk; }; typedef struct malloc_chunk* mchunkptr; struct malloc_bin { struct malloc_chunk hd; /* dummy list header */ unsigned int dirty; /* True if maybe consolidatable */ /* Wasting a word here makes */ /* sizeof(bin) a power of 2, */ /* which makes size2bin() faster */ }; typedef struct malloc_bin* mbinptr; /* sizes, alignments */ #define SIZE_SZ (sizeof(unsigned int)) #define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ) #define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1) #define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ) /* MUST == 16! */ /* pad request bytes into a usable size */ static inline unsigned int request2size(unsigned int request) { return (request == 0) ? MINSIZE : ((request + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)); } static inline int aligned_OK(void* m) { return ((unsigned int)(m) & (MALLOC_ALIGN_MASK)) == 0; } /* size field or'd with INUSE when in use */ #define INUSE 0x1 /* the bins, initialized to have null double linked lists */ #define MAXBIN 120 /* 1 more than needed for 32 bit addresses */ #define FIRSTBIN (&(av[0])) static struct malloc_bin av[MAXBIN] = { { { 0, &(av[0].hd), &(av[0].hd) }, 0 }, { { 0, &(av[1].hd), &(av[1].hd) }, 0 }, { { 0, &(av[2].hd), &(av[2].hd) }, 0 }, { { 0, &(av[3].hd), &(av[3].hd) }, 0 }, { { 0, &(av[4].hd), &(av[4].hd) }, 0 }, { { 0, &(av[5].hd), &(av[5].hd) }, 0 }, { { 0, &(av[6].hd), &(av[6].hd) }, 0 }, { { 0, &(av[7].hd), &(av[7].hd) }, 0 }, { { 0, &(av[8].hd), &(av[8].hd) }, 0 }, { { 0, &(av[9].hd), &(av[9].hd) }, 0 }, { { 0, &(av[10].hd), &(av[10].hd) }, 0 }, { { 0, &(av[11].hd), &(av[11].hd) }, 0 }, { { 0, &(av[12].hd), &(av[12].hd) }, 0 }, { { 0, &(av[13].hd), &(av[13].hd) }, 0 }, { { 0, &(av[14].hd), &(av[14].hd) }, 0 }, { { 0, &(av[15].hd), &(av[15].hd) }, 0 }, { { 0, &(av[16].hd), &(av[16].hd) }, 0 }, { { 0, &(av[17].hd), &(av[17].hd) }, 0 }, { { 0, &(av[18].hd), &(av[18].hd) }, 0 }, { { 0, &(av[19].hd), &(av[19].hd) }, 0 }, { { 0, &(av[20].hd), &(av[20].hd) }, 0 }, { { 0, &(av[21].hd), &(av[21].hd) }, 0 }, { { 0, &(av[22].hd), &(av[22].hd) }, 0 }, { { 0, &(av[23].hd), &(av[23].hd) }, 0 }, { { 0, &(av[24].hd), &(av[24].hd) }, 0 }, { { 0, &(av[25].hd), &(av[25].hd) }, 0 }, { { 0, &(av[26].hd), &(av[26].hd) }, 0 }, { { 0, &(av[27].hd), &(av[27].hd) }, 0 }, { { 0, &(av[28].hd), &(av[28].hd) }, 0 }, { { 0, &(av[29].hd), &(av[29].hd) }, 0 }, { { 0, &(av[30].hd), &(av[30].hd) }, 0 }, { { 0, &(av[31].hd), &(av[31].hd) }, 0 }, { { 0, &(av[32].hd), &(av[32].hd) }, 0 }, { { 0, &(av[33].hd), &(av[33].hd) }, 0 }, { { 0, &(av[34].hd), &(av[34].hd) }, 0 }, { { 0, &(av[35].hd), &(av[35].hd) }, 0 }, { { 0, &(av[36].hd), &(av[36].hd) }, 0 }, { { 0, &(av[37].hd), &(av[37].hd) }, 0 }, { { 0, &(av[38].hd), &(av[38].hd) }, 0 }, { { 0, &(av[39].hd), &(av[39].hd) }, 0 }, { { 0, &(av[40].hd), &(av[40].hd) }, 0 }, { { 0, &(av[41].hd), &(av[41].hd) }, 0 }, { { 0, &(av[42].hd), &(av[42].hd) }, 0 }, { { 0, &(av[43].hd), &(av[43].hd) }, 0 }, { { 0, &(av[44].hd), &(av[44].hd) }, 0 }, { { 0, &(av[45].hd), &(av[45].hd) }, 0 }, { { 0, &(av[46].hd), &(av[46].hd) }, 0 }, { { 0, &(av[47].hd), &(av[47].hd) }, 0 }, { { 0, &(av[48].hd), &(av[48].hd) }, 0 }, { { 0, &(av[49].hd), &(av[49].hd) }, 0 }, { { 0, &(av[50].hd), &(av[50].hd) }, 0 }, { { 0, &(av[51].hd), &(av[51].hd) }, 0 }, { { 0, &(av[52].hd), &(av[52].hd) }, 0 }, { { 0, &(av[53].hd), &(av[53].hd) }, 0 }, { { 0, &(av[54].hd), &(av[54].hd) }, 0 }, { { 0, &(av[55].hd), &(av[55].hd) }, 0 }, { { 0, &(av[56].hd), &(av[56].hd) }, 0 }, { { 0, &(av[57].hd), &(av[57].hd) }, 0 }, { { 0, &(av[58].hd), &(av[58].hd) }, 0 }, { { 0, &(av[59].hd), &(av[59].hd) }, 0 }, { { 0, &(av[60].hd), &(av[60].hd) }, 0 }, { { 0, &(av[61].hd), &(av[61].hd) }, 0 }, { { 0, &(av[62].hd), &(av[62].hd) }, 0 }, { { 0, &(av[63].hd), &(av[63].hd) }, 0 }, { { 0, &(av[64].hd), &(av[64].hd) }, 0 }, { { 0, &(av[65].hd), &(av[65].hd) }, 0 }, { { 0, &(av[66].hd), &(av[66].hd) }, 0 }, { { 0, &(av[67].hd), &(av[67].hd) }, 0 }, { { 0, &(av[68].hd), &(av[68].hd) }, 0 }, { { 0, &(av[69].hd), &(av[69].hd) }, 0 }, { { 0, &(av[70].hd), &(av[70].hd) }, 0 }, { { 0, &(av[71].hd), &(av[71].hd) }, 0 }, { { 0, &(av[72].hd), &(av[72].hd) }, 0 }, { { 0, &(av[73].hd), &(av[73].hd) }, 0 }, { { 0, &(av[74].hd), &(av[74].hd) }, 0 }, { { 0, &(av[75].hd), &(av[75].hd) }, 0 }, { { 0, &(av[76].hd), &(av[76].hd) }, 0 }, { { 0, &(av[77].hd), &(av[77].hd) }, 0 }, { { 0, &(av[78].hd), &(av[78].hd) }, 0 }, { { 0, &(av[79].hd), &(av[79].hd) }, 0 }, { { 0, &(av[80].hd), &(av[80].hd) }, 0 }, { { 0, &(av[81].hd), &(av[81].hd) }, 0 }, { { 0, &(av[82].hd), &(av[82].hd) }, 0 }, { { 0, &(av[83].hd), &(av[83].hd) }, 0 }, { { 0, &(av[84].hd), &(av[84].hd) }, 0 }, { { 0, &(av[85].hd), &(av[85].hd) }, 0 }, { { 0, &(av[86].hd), &(av[86].hd) }, 0 }, { { 0, &(av[87].hd), &(av[87].hd) }, 0 }, { { 0, &(av[88].hd), &(av[88].hd) }, 0 }, { { 0, &(av[89].hd), &(av[89].hd) }, 0 }, { { 0, &(av[90].hd), &(av[90].hd) }, 0 }, { { 0, &(av[91].hd), &(av[91].hd) }, 0 }, { { 0, &(av[92].hd), &(av[92].hd) }, 0 }, { { 0, &(av[93].hd), &(av[93].hd) }, 0 }, { { 0, &(av[94].hd), &(av[94].hd) }, 0 }, { { 0, &(av[95].hd), &(av[95].hd) }, 0 }, { { 0, &(av[96].hd), &(av[96].hd) }, 0 }, { { 0, &(av[97].hd), &(av[97].hd) }, 0 }, { { 0, &(av[98].hd), &(av[98].hd) }, 0 }, { { 0, &(av[99].hd), &(av[99].hd) }, 0 }, { { 0, &(av[100].hd), &(av[100].hd) }, 0 }, { { 0, &(av[101].hd), &(av[101].hd) }, 0 }, { { 0, &(av[102].hd), &(av[102].hd) }, 0 }, { { 0, &(av[103].hd), &(av[103].hd) }, 0 }, { { 0, &(av[104].hd), &(av[104].hd) }, 0 }, { { 0, &(av[105].hd), &(av[105].hd) }, 0 }, { { 0, &(av[106].hd), &(av[106].hd) }, 0 }, { { 0, &(av[107].hd), &(av[107].hd) }, 0 }, { { 0, &(av[108].hd), &(av[108].hd) }, 0 }, { { 0, &(av[109].hd), &(av[109].hd) }, 0 }, { { 0, &(av[110].hd), &(av[110].hd) }, 0 }, { { 0, &(av[111].hd), &(av[111].hd) }, 0 }, { { 0, &(av[112].hd), &(av[112].hd) }, 0 }, { { 0, &(av[113].hd), &(av[113].hd) }, 0 }, { { 0, &(av[114].hd), &(av[114].hd) }, 0 }, { { 0, &(av[115].hd), &(av[115].hd) }, 0 }, { { 0, &(av[116].hd), &(av[116].hd) }, 0 }, { { 0, &(av[117].hd), &(av[117].hd) }, 0 }, { { 0, &(av[118].hd), &(av[118].hd) }, 0 }, { { 0, &(av[119].hd), &(av[119].hd) }, 0 } }; /* indexing into bins */ static inline mbinptr size2bin(unsigned int sz) { mbinptr b = av; while (sz >= (MINSIZE * 2)) { b += 4; sz >>= 1; } /* find power of 2 */ b += (sz - MINSIZE) >> 2; /* find quadrant */ return b; } /* counts maintained if MALLOC_STATS defined */ #ifdef MALLOC_STATS static unsigned int sbrked_mem; static unsigned int requested_mem; static unsigned int malloced_mem; static unsigned int freed_mem; static unsigned int max_used_mem; static unsigned int n_sbrks; static unsigned int n_mallocs; static unsigned int n_frees; static unsigned int n_reallocs; static unsigned int n_reallocs_with_copy; static unsigned int n_avail; static unsigned int max_inuse; static unsigned int n_malloc_chunks; static unsigned int n_malloc_bins; static unsigned int n_split; static unsigned int n_consol; static void do_malloc_stats(const mchunkptr p) { ++n_mallocs; if ((n_mallocs-n_frees) > max_inuse) max_inuse = n_mallocs - n_frees; malloced_mem += (p->size & ~(INUSE)); if (malloced_mem - freed_mem > max_used_mem) max_used_mem = malloced_mem - freed_mem; } static void do_free_stats(const mchunkptr p) { ++n_frees; freed_mem += (p->size & ~(INUSE)); } #endif /* maintaining INUSE via size field */ #define inuse(p) ((p)->size & INUSE) #define set_inuse(p) ((p)->size |= INUSE) #define clear_inuse(b) ((p)->size &= ~INUSE) /* operations on malloc_chunk addresses */ /* return ptr to next physical malloc_chunk */ #define next_chunk(p) ((mchunkptr)((char*)(p) + (p)->size)) /* return ptr to previous physical malloc_chunk */ #define prev_chunk(p) ((mchunkptr)((char*)(p)-((((int*)(p))[-1]) & ~(INUSE)))) /* place size at front and back of chunk */ static inline void set_size(mchunkptr p, unsigned int sz) { p->size = *((int*)((char*)(p) + sz - SIZE_SZ)) = sz; } /* conversion from malloc headers to user pointers, and back */ static inline void* chunk2mem(mchunkptr p) { set_inuse(p); return (void*)((char*)(p) + SIZE_SZ); } static inline mchunkptr mem2chunk(void* mem) { mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ); /* a quick sanity check */ unsigned int sz = p->size & ~(INUSE); if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ))) malloc_user_error(); p->size = sz; /* clears INUSE */ return p; } /* maintaining bins & pointers */ /* maximum bin actually used */ static mbinptr malloc_maxbin = FIRSTBIN; /* The designated victim bin. */ static mbinptr malloc_victim = FIRSTBIN; /* operations on lists inside bins */ /* take a chunk off a list */ static inline void unlink(mchunkptr p) { mchunkptr b = p->bk; mchunkptr f = p->fd; f->bk = b; b->fd = f; UPDATE_STATS (--n_avail); } /* split a chunk and place on the back of a list */ static inline void split(mchunkptr p, unsigned int offset) { unsigned int room = p->size - offset; if (room >= MINSIZE) { mbinptr bn = size2bin(room); /* new bin */ mchunkptr h = &(bn->hd); /* its head */ mchunkptr b = h->bk; /* old back element */ mchunkptr t = (mchunkptr)((char*)(p) + offset); /* remaindered chunk */ /* set size */ t->size = *((int*)((char*)(t) + room - SIZE_SZ)) = room; /* link up */ t->bk = b; t->fd = h; h->bk = b->fd = t; /* adjust maxbin (h == b means was empty) */ if (h == b && bn > malloc_maxbin) malloc_maxbin = bn; /* use as next victim */ malloc_victim = bn; /* adjust size of chunk to be returned */ p->size = *((int*)((char*)(p) + offset - SIZE_SZ)) = offset; UPDATE_STATS ((++n_split, ++n_avail)); } } /* place a consolidated chunk on the back of a list */ /* like above, except no split */ static inline void consollink(mchunkptr p) { mbinptr bn = size2bin(p->size); mchunkptr h = &(bn->hd); mchunkptr b = h->bk; p->bk = b; p->fd = h; h->bk = b->fd = p; if (h == b && bn > malloc_maxbin) malloc_maxbin = bn; malloc_victim = bn; /* use as next victim */ UPDATE_STATS(++n_avail); } /* place a freed chunk on the front of a list */ static inline void frontlink(mchunkptr p) { mbinptr bn = size2bin(p->size); mchunkptr h = &(bn->hd); mchunkptr f = h->fd; p->bk = h; p->fd = f; f->bk = h->fd = p; if (h == f && bn > malloc_maxbin) malloc_maxbin = bn; bn->dirty = 1; UPDATE_STATS(++n_avail); } /* Dealing with sbrk */ /* To link consecutive sbrk regions when possible */ static int* last_sbrk_end; /* who to call when sbrk returns failure */ #ifndef NO_NEW_HANDLER typedef volatile void (*vfp)(); #ifdef __cplusplus extern "C" vfp __new_handler; #else extern vfp __new_handler; #endif #endif static mchunkptr malloc_from_sys(unsigned nb) { mchunkptr p; unsigned int sbrk_size; int* ip; /* Minimally, we need to pad with enough space */ /* to place dummy size/use fields to ends if needed */ sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ) / SBRK_UNIT) * SBRK_UNIT; ip = (int*)(sbrk(sbrk_size)); if ((char*)ip == (char*)(-1)) /* sbrk returns -1 on failure */ { #ifndef NO_NEW_HANDLER (*__new_handler) (); #endif return 0; } UPDATE_STATS ((++n_sbrks, sbrked_mem += sbrk_size)); if (last_sbrk_end != &ip[-1]) { /* It's either first time through or someone else called sbrk. */ /* Arrange end-markers at front & back */ /* Shouldn't be necessary, but better to be safe */ while (!aligned_OK(ip)) { ++ip; sbrk_size -= SIZE_SZ; } /* Mark the front as in use to prevent merging. */ /* Note we can get away with only 1 word, not MINSIZE overhead here */ *ip++ = SIZE_SZ | INUSE; p = (mchunkptr)ip; set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ)); } else { mchunkptr l; /* We can safely make the header start at end of prev sbrked chunk. */ /* We will still have space left at the end from a previous call */ /* to place the end marker, below */ p = (mchunkptr)(last_sbrk_end); set_size(p, sbrk_size); /* Even better, maybe we can merge with last fragment: */ l = prev_chunk(p); if (!inuse(l)) { unlink(l); set_size(l, p->size + l->size); p = l; } } /* mark the end of sbrked space as in use to prevent merging */ last_sbrk_end = (int*)((char*)p + p->size); *last_sbrk_end = SIZE_SZ | INUSE; UPDATE_STATS((++n_avail, ++n_malloc_chunks)); return p; } /* Consolidate dirty bins. */ /* Stop if found a chunk big enough to satisfy current malloc request */ /* (It requires much less bookkeeping to consolidate entire bins */ /* at once than to keep records of which chunks might be */ /* consolidatable. So long as the lists are short, which we */ /* try to ensure via small bin ranges, there is little wasted effort.) */ static mchunkptr malloc_find_space(unsigned int nb) { mbinptr b; mchunkptr usable = 0; /* first, re-adjust max used bin */ while (malloc_maxbin >= FIRSTBIN && malloc_maxbin->hd.bk == &(malloc_maxbin->hd)) { malloc_maxbin->dirty = 0; --malloc_maxbin; } for (b = malloc_maxbin; b >= FIRSTBIN; --b) { UPDATE_STATS(++n_malloc_bins); if (b->dirty) { mchunkptr h = &(b->hd); /* head of list */ mchunkptr p = h->bk; /* chunk traverser */ while (p != h) { mchunkptr nextp = p->bk; /* save, in case of relinks */ int consolidated = 0; /* only unlink/relink if consolidated */ mchunkptr t; while (!inuse(t = prev_chunk(p))) /* consolidate backward */ { if (!consolidated) { consolidated = 1; unlink(p); } if (t == nextp) nextp = t->bk; unlink(t); set_size(t, t->size + p->size); p = t; UPDATE_STATS (++n_consol); } while (!inuse(t = next_chunk(p))) /* consolidate forward */ { if (!consolidated) { consolidated = 1; unlink(p); } if (t == nextp) nextp = t->bk; unlink(t); set_size(p, p->size + t->size); UPDATE_STATS (++n_consol); } if (consolidated) { consollink(p); if (p->size >= nb) usable = p; } UPDATE_STATS(++n_malloc_chunks); p = nextp; } b->dirty = 0; if (usable != 0) { unlink(usable); return usable; } } } /* nothing available - sbrk some more */ return malloc_from_sys(nb); } /* Finally, the user-level functions */ void* malloc(unsigned int bytes) { unsigned int nb = request2size(bytes); /* padded request size */ mbinptr b = size2bin(nb); /* corresponding bin */ mchunkptr hd = &(b->hd); /* head of its list */ mchunkptr p; /* chunk traverser */ UPDATE_STATS((requested_mem+=bytes, ++n_malloc_bins)); /* Try a (near) exact match in own bin */ for (p = hd->fd; p != hd; p = p->fd) { UPDATE_STATS(++n_malloc_chunks); if (p->size >= nb) { unlink(p); goto found; } } /* No exact match, so select a victim */ UPDATE_STATS(++n_malloc_chunks); p = malloc_victim->hd.bk; if (p->size >= nb) unlink(p); else { /* Find a new victim. */ for (;;) { UPDATE_STATS(++n_malloc_bins); ++b; p = b->hd.bk; if (p != &(b->hd)) { /* p must be usable since it's in bigger bin */ /* Consolidate, so it can serve as a victim longer */ mchunkptr t; unlink(p); while (!inuse(t = prev_chunk(p))) /* consolidate backward */ { unlink(t); set_size(t, t->size + p->size); p = t; UPDATE_STATS (++n_consol); } while (!inuse(t = next_chunk(p))) /* consolidate forward */ { unlink(t); set_size(p, p->size + t->size); UPDATE_STATS (++n_consol); } malloc_victim = b; /* record this bin for next time */ break; } else if (b > malloc_maxbin) { p = malloc_find_space(nb); if (p == 0) return 0; else break; } } } /* use what we found */ found: split(p, nb); UPDATE_STATS(do_malloc_stats(p)); return chunk2mem(p); } void free(void* mem) { if (mem != 0) { mchunkptr p = mem2chunk(mem); UPDATE_STATS(do_free_stats(p)); frontlink(p); } } void* calloc(unsigned int elem_size, unsigned int n) { unsigned int sz = n * elem_size; void* p = malloc(sz); bzero(p, sz); return p; }; /* This is here for compatibility with older systems */ void cfree(void *mem, unsigned int n, unsigned int elem_size) { free(mem); } unsigned int malloc_usable_size(void* mem) { if (mem == 0) return 0; else { mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ); unsigned int sz = p->size & ~(INUSE); if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ))) return 0; else return sz - MALLOC_MIN_OVERHEAD; } } void* realloc(void* mem, unsigned int bytes) { if (mem == 0) return malloc(bytes); else { unsigned int nb = request2size(bytes); mchunkptr p = mem2chunk(mem); unsigned int oldsize = p->size; int room; mchunkptr nxt; UPDATE_STATS((++n_reallocs, requested_mem += bytes-oldsize)); /* try to expand (even if already big enough), to clean up chunk */ while (!inuse(nxt = next_chunk(p))) { UPDATE_STATS ((malloced_mem += nxt->size, ++n_consol)); unlink(nxt); set_size(p, p->size + nxt->size); } room = p->size - nb; if (room >= 0) { if (room >= MINSIZE) { split(p, nb); UPDATE_STATS(malloced_mem -= room); } return chunk2mem(p); } else /* do the obvious */ { void* newmem; set_inuse(p); /* don't let malloc consolidate us yet! */ newmem = malloc(nb); bcopy(mem, newmem, oldsize - SIZE_SZ); free(mem); UPDATE_STATS(++n_reallocs_with_copy); return newmem; } } } void malloc_stats() { #ifndef MALLOC_STATS } #else int i; mchunkptr p; double nm = (double)(n_mallocs + n_reallocs); fprintf(stderr, "\nmalloc statistics\n\n"); if (n_mallocs != 0) fprintf(stderr, "requests = %10u total size = %10u\tave = %10u\n", n_mallocs, requested_mem, requested_mem/n_mallocs); if (n_mallocs != 0) fprintf(stderr, "mallocs = %10u total size = %10u\tave = %10u\n", n_mallocs, malloced_mem, malloced_mem/n_mallocs); if (n_frees != 0) fprintf(stderr, "frees = %10u total size = %10u\tave = %10u\n", n_frees, freed_mem, freed_mem/n_frees); if (n_mallocs-n_frees != 0) fprintf(stderr, "in use = %10u total size = %10u\tave = %10u\n", n_mallocs-n_frees, malloced_mem-freed_mem, (malloced_mem-freed_mem) / (n_mallocs-n_frees)); if (max_inuse != 0) fprintf(stderr, "max in use= %10u total size = %10u\tave = %10u\n", max_inuse, max_used_mem, max_used_mem / max_inuse); if (n_avail != 0) fprintf(stderr, "available = %10u total size = %10u\tave = %10u\n", n_avail, sbrked_mem - (malloced_mem-freed_mem), (sbrked_mem - (malloced_mem-freed_mem)) / n_avail); if (n_sbrks != 0) fprintf(stderr, "sbrks = %10u total size = %10u\tave = %10u\n\n", n_sbrks, sbrked_mem, sbrked_mem/ n_sbrks); if (n_reallocs != 0) fprintf(stderr, "reallocs = %10u with copy = %10u\n\n", n_reallocs, n_reallocs_with_copy); if (nm != 0) { fprintf(stderr, "chunks scanned per malloc = %6.3f\n", n_malloc_chunks / nm); fprintf(stderr, "bins scanned per malloc = %6.3f\n", n_malloc_bins / nm); fprintf(stderr, "splits per malloc = %6.3f\n", n_split / nm); fprintf(stderr, "consolidations per malloc = %6.3f\n", n_consol / nm); } fprintf(stderr, "\nfree chunks:\n"); for (i = 0; i < MAXBIN; ++i) { p = av[i].hd.fd; if (p != &(av[i].hd)) { unsigned int count = 1; unsigned int sz = p->size; for (p = p->fd; p != &(av[i].hd); p = p->fd) { if (p->size == sz) ++count; else { fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count); count = 1; sz = p->size; } } fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count); } } } #endif /* MALLOC_STATS */ #endif /* NO_LIBGXX_MALLOC */ p = av[i].hd.fd; if (p != &(av[i].hd)) { unsigned int count = 1; unsigned int sz = p->size; for (p = p->fd; p != &(av[i].hd); p = p->fd) { libg++/src/EH.cc 644 473 0 1307 4677700053 6531 /* Library code for programs which use -fhandle-exceptions. Note: do *not* compile this with -fhandle-exceptions. */ #include #include struct ExceptionHandler { ExceptionHandler *prev; jmp_buf handler; void *name; void *parameters; ExceptionHandler (); ~ExceptionHandler (); } EHS, *exceptionHandlerStack = &EHS; ExceptionHandler::ExceptionHandler () { if (this == &EHS) { if (setjmp (EHS.handler)) { cerr << ("unhandled exception, aborting...\n"); abort (); } } else { this->prev = exceptionHandlerStack; exceptionHandlerStack = this; } } ExceptionHandler::~ExceptionHandler () { exceptionHandlerStack = this->prev; } onHandler *prev; jmp_buf handler; void *name; void *parameters; ExceptionHandler (); ~ExceptionHandler (); } EHS, *exceptionHandlerStack = &EHS; ExceptionHandler::ExceptionHandler () { if (this == &EHS) { if (setjmp (EHS.handler)) { cerr << ("unhandled exception, aborting...\n"); ablibg++/src/sqrt.cc 644 473 0 2273 4677700053 7231 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include long sqrt(long x) { if (x <= 0) return 0; // no int error handler, so ... else if (x == 1) return 1; else { long r = x >> 1; long q; for(;;) { q = x / r; if (q >= r) return r; else r = (r + q) >> 1; } } } n know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include long sqrt(long x) { if (x <= 0) return 0; // no int error handler, so ... else if libg++/src/lg.cc 644 473 0 1752 4677700054 6644 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include long lg(unsigned long x) { long l = 0; while (x > 1) { x = x >> 1; ++l; } return l; } to copy, modify and relibg++/src/libgxx_fmtq.cc 644 473 0 2135 4677700054 10562 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include // AllocRings are used for output operations // We guaranteee that the last _libgxx_maxfmt formats // will be intact static const int _libgxx_maxfmt = 20; AllocRing _libgxx_fmtq(_libgxx_maxfmt); se. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include // AllocRings are used for output operations // We guaranteee that the last _libgxx_maxfmt formats // wlibg++/src/xyzzy.cc 644 473 0 325 4677700054 7432 #ifndef NO_GNULIB3 // from tiemann /* Needed, in case there are no other objects which need static initialization and cleanup. */ struct __xyzzy__ { __xyzzy__ () {} ~__xyzzy__ () {} } __1xyzzy__; #endif ponsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include // AllocRings are used for output operations // We guaranteee that the last _libgxx_maxfmt formats // wlibg++/src/AllocRing.cc 644 473 0 4441 4677700054 10112 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include AllocRing::AllocRing(int max) :n(max), current(0), nodes(new AllocQNode[max]) { for (int i = 0; i < n; ++i) { nodes[i].ptr = 0; nodes[i].sz = 0; } } int AllocRing::find(void* p) { if (p == 0) return -1; for (int i = 0; i < n; ++i) if (nodes[i].ptr == p) return i; return -1; } void AllocRing::clear() { for (int i = 0; i < n; ++i) { if (nodes[i].ptr != 0) { delete(nodes[i].ptr); nodes[i].ptr = 0; } nodes[i].sz = 0; } current = 0; } void AllocRing::free(void* p) { int idx = find(p); if (idx >= 0) { delete nodes[idx].ptr; nodes[idx].ptr = 0; } } AllocRing::~AllocRing() { clear(); } int AllocRing::contains(void* p) { return find(p) >= 0; } static inline unsigned int good_size(unsigned int s) { unsigned int req = s + 4; unsigned int good = 8; while (good < req) good <<= 1; return good - 4; } void* AllocRing::alloc(int s) { unsigned int size = good_size(s); void* p; if (nodes[current].ptr != 0 && nodes[current].sz >= size && nodes[current].sz < (4 * size)) p = nodes[current].ptr; else { if (nodes[current].ptr != 0) delete nodes[current].ptr; p = new char[size]; nodes[current].ptr = p; nodes[current].sz = size; } ++current; if (current >= n) current = 0; return p; } ed int good = 8; while (good < req) good <<= 1; return good - 4; } void* AllocRing::alloc(int s) { unsigned int size = good_size(s); void* p; if (nodes[current].ptr != 0 && nodes[current].sz >= size && libg++/src/pow.cc 644 473 0 3174 4677700054 7047 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include double pow(double x, long p) { if (p == 0) return (x < 0 && (p & 1)) ? -1.0 : 1.0; else if (x == 0.0) return 0.0; else { double b; if (p < 0) { p = -p; b = 1.0 / x; } else b = x; double r = 1.0; for(;;) { if (p & 1) r *= b; if ((p >>= 1) == 0) return r; else b *= b; } } } long pow(long x, long y) { if (x == 0) return (y == 0)? 1 : 0; else if (y < 0) return 0; else if (y == 0 || x == 1) return 1; else if (x == -1) return (y & 1)? -1 : 1; else { long r = 1; for(;;) { if (y & 1) r *= x; if ((y >>= 1) == 0) return r; else x *= x; } } } double r = 1.0; for(;;) { if (p & 1) r *= b; if ((p >>= 1) == 0) return r; else b *= b; } } } long pow(long x, long y) { if (x == 0) return (y == 0)? 1 : 0; else if (y < 0) return 0; else if (y == 0 || x == 1) return 1; else if (x == -1) return (y & 1)? -1 : 1; else { long r = 1; for(;;libg++/src/gcd.cc 644 473 0 2353 4677700055 6776 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include /* common functions on built-in types */ long gcd(long x, long y) // euclid's algorithm { long a = abs(x); long b = abs(y); long tmp; if (b > a) { tmp = a; a = b; b = tmp; } for(;;) { if (b == 0) return a; else if (b == 1) return b; else { tmp = b; b = a % b; a = tmp; } } } uld be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include /* common functions on built-in types */ long gcd(long x, long y) // euclid's algorithm { long a = abs(x); long libg++/src/Binomial.cc 644 473 0 2126 4677700055 7771 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Binomial::operator()() { int s = 0; for (int i = 0; i < pN; i++) { if (pGenerator -> asDouble() < pU) { s++; } } return(double(s)); } Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Binomial::operator()() { int s = 0; for (int i = 0; i < pN; i++libg++/src/form.cc 644 473 0 2501 4677700055 7177 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include extern AllocRing _libgxx_fmtq; char* form(const char* fmt ...) { va_list args; va_start(args, fmt); char* fmtbase = (char *) _libgxx_fmtq.alloc(BUFSIZ); #ifndef HAVE_VPRINTF FILE b; b._flag = _IOWRT|_IOSTRG; b._ptr = fmtbase; b._cnt = BUFSIZ-1; _doprnt(fmt, args, &b); putc('\0', &b); #else vsprintf(fmtbase, fmt, args); #endif va_end(args); return fmtbase; } ice must be preserved on all copies. */ #include #include #include #include extern AllocRing _libgxx_fmtq; char* form(const char* fmt ...) libg++/src/itoa.cc 644 473 0 7707 4677700056 7206 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include extern AllocRing _libgxx_fmtq; char* itoa(long x, int base, int width) { int wrksiz; if (base == 10) wrksiz = width + 13; else wrksiz = (BITS(long) + 1) / lg(base) + 1 + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* e = fmtbase + wrksiz - 1; char* s = e; *--s = 0; char sgn = 0; if (x == 0) *--s = '0'; else { unsigned int z; if (x < 0) { sgn = '-'; z = -x; } else z = x; while (z != 0) { char ch = char(z % base); z = z / base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } if (sgn) *--s = sgn; int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } char* itoa(unsigned long x, int base, int width) { int wrksiz; if (base == 10) wrksiz = width + 13; else wrksiz = (BITS(long) + 1) / lg(base) + 1 + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* e = fmtbase + wrksiz - 1; char* s = e; *--s = 0; if (x == 0) *--s = '0'; else { unsigned int b = base; while (x != 0) { char ch = char(x % b); x = x / b; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } #ifdef __GNUG__ char* itoa(long long x, int base, int width) { int wrksiz; if (base == 10) wrksiz = width + 23; else wrksiz = (BITS(long long) + 1) / lg(base) + 1 + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* e = fmtbase + wrksiz - 1; char* s = e; *--s = 0; char sgn = 0; if (x == 0) *--s = '0'; else { long long z; if (x < 0) { sgn = '-'; z = -x; } else z = x; while (z != 0) { char ch = char(z % base); z = z / base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } if (sgn) *--s = sgn; int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } char* itoa(unsigned long long x, int base, int width) { int wrksiz; if (base == 10) wrksiz = width + 23; else wrksiz = (BITS(long long) + 1) / lg(base) + 1 + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* e = fmtbase + wrksiz - 1; char* s = e; *--s = 0; if (x == 0) *--s = '0'; else { unsigned int b = base; while (x != 0) { char ch = char(x % b); x = x / b; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } int w = e - s - 1; while (w++ < width) *--s = ' '; return s; } #endif char* hex(long i, int width) { return itoa(i, 16, width); } char* oct(long i, int width) { return itoa(i, 8, width); } char* dec(long i, int width) { return itoa(i, 10, width); } char* hex(unsigned long i, int width) { return itoa(i, 16, width); } char* oct(unsigned long i, int width) { return itoa(i, 8, width); } char* dec(unsigned long i, int width) { return itoa(i, 10, width); } *--s = ch; } } int w = e - s - 1; whilelibg++/src/chr.cc 644 473 0 2315 4677700056 7014 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include extern AllocRing _libgxx_fmtq; char* chr(char ch, int width) { int len = 1; int wrksiz = len + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* fmt = fmtbase; for (int blanks = width - len; blanks > 0; --blanks) *fmt++ = ' '; *fmt++ = ch; *fmt = 0; return fmtbase; } and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include extern AllocRing _libgxx_fmtq; char* chr(char ch, int width) { int len = 1; int wrksiz = len + widlibg++/src/dtoa.cc 644 473 0 15741 4677700056 7216 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include extern AllocRing _libgxx_fmtq; char* dtoa(double fpnum, char cvt, int width, int prec) { // set up workspace // max possible digits <= those need to show all of prec + exp // <= ceil(log10(HUGE)) plus space for null, etc. const int worksiz = int(M_LN2 * DMAXEXP) + 8; // for fractional part char fwork[worksiz]; char* fw = fwork; // for integer part char iwork[worksiz]; char* iworkend = &iwork[sizeof(iwork) - 1]; char* iw = iworkend; *iw = 0; // for exponent part const int eworksiz = int(M_LN2 * _DEXPLEN) + 8; char ework[eworksiz]; char* eworkend = &ework[sizeof(ework) - 1]; char* ew = eworkend; *ew = 0; #if (_IEEE != 0) if (isinf(fpnum)) { char* inffmt = (char *) _libgxx_fmtq.alloc(5); char* inffmtp = inffmt; if (fpnum < 0) *inffmtp++ = '-'; strcpy(inffmtp, "Inf"); return inffmt; } if (isnan(fpnum)) { char* nanfmt = (char *) _libgxx_fmtq.alloc(4); strcpy(nanfmt, "NaN"); return nanfmt; } #endif // grab sign & make non-negative int is_neg = fpnum < 0; if (is_neg) fpnum = -fpnum; // precision matters if (prec > worksiz - 2) // can't have more prec than supported prec = worksiz - 2; double powprec; if (prec == 6) powprec = 1.0e6; else powprec = pow(10.0, (long) prec); double rounder = 0.5 / powprec; int f_fmt = cvt == 'f' || ((cvt == 'g') && (fpnum == 0.0 || (fpnum >= 1e-4 && fpnum < powprec))); int iwidth = 0; int fwidth = 0; int ewidth = 0; if (f_fmt) // fixed format { double ipart; double fpart = modf(fpnum, &ipart); // convert fractional part if (fpart >= rounder || cvt != 'g') { fpart += rounder; if (fpart >= 1.0) { ipart += 1.0; fpart -= 1.0; } double ffpart = fpart; double ifpart; for (int i = 0; i < prec; ++i) { ffpart = modf(ffpart * 10.0, &ifpart); *fw++ = '0' + int(ifpart); ++fwidth; } if (cvt == 'g') // inhibit trailing zeroes if g-fmt { for (char* p = fw - 1; p >= fwork && *p == '0'; --p) { *p = 0; --fwidth; } } } // convert integer part if (ipart == 0.0) { if (cvt != 'g' || fwidth < prec || fwidth < width) { *--iw = '0'; ++iwidth; } } else if (ipart <= double(MAXLONG)) // a useful speedup { long li = long(ipart); while (li != 0) { *--iw = '0' + (li % 10); li = li / 10; ++iwidth; } } else // the slow way { while (ipart > 0.5) { double ff = modf(ipart / 10.0, &ipart); ff = (ff + 0.05) * 10.0; *--iw = '0' + int(ff); ++iwidth; } } // g-fmt: kill part of frac if prec/width exceeded if (cvt == 'g') { int m = prec; if (m < width) m = width; int adj = iwidth + fwidth - m; if (adj > fwidth) adj = fwidth; if (adj > 0) { for (char* f = &fwork[fwidth-1]; f >= fwork && adj > 0; --adj, --f) { --fwidth; char ch = *f; *f = 0; if (ch > '5') // properly round: unavoidable propagation { int carry = 1; for (char* p = f - 1; p >= fwork && carry; --p) { ++*p; if (*p > '9') *p = '0'; else carry = 0; } if (carry) { for (p = iworkend - 1; p >= iw && carry; --p) { ++*p; if (*p > '9') *p = '0'; else carry = 0; } if (carry) { *--iw = '1'; ++iwidth; --adj; } } } } } } } else // e-fmt { // normalize int exp = 0; while (fpnum >= 10.0) { fpnum *= 0.1; ++exp; } while (fpnum > 0.0 && fpnum < 1.0) { fpnum *= 10.0; --exp; } double ipart; double fpart = modf(fpnum, &ipart); if (cvt == 'g') // used up one digit for int part... { --prec; powprec /= 10.0; rounder = 0.5 / powprec; } // convert fractional part -- almost same as above if (fpart >= rounder || cvt != 'g') { fpart += rounder; if (fpart >= 1.0) { fpart -= 1.0; ipart += 1.0; if (ipart >= 10.0) { ++exp; ipart /= 10.0; fpart /= 10.0; } } double ffpart = fpart; double ifpart; for (int i = 0; i < prec; ++i) { ffpart = modf(ffpart * 10.0, &ifpart); *fw++ = '0' + int(ifpart); ++fwidth; } if (cvt == 'g') // inhibit trailing zeroes if g-fmt { for (char* p = fw - 1; p >= fwork && *p == '0'; --p) { *p = 0; --fwidth; } } } // convert exponent char eneg = exp < 0; if (eneg) exp = - exp; while (exp > 0) { *--ew = '0' + (exp % 10); exp /= 10; ++ewidth; } while (ewidth < 2) // ensure at least 2 zeroes { *--ew = '0'; ++ewidth; } *--ew = eneg ? '-' : '+'; *--ew = 'e'; ewidth += 2; // convert the one-digit integer part *--iw = '0' + int(ipart); ++iwidth; } // arrange everything in returned string int showdot = cvt != 'g' || fwidth > 0; int fmtwidth = is_neg + iwidth + showdot + fwidth + ewidth; int pad = width - fmtwidth; if (pad < 0) pad = 0; char* fmtbase = (char *) _libgxx_fmtq.alloc(fmtwidth + pad + 1); char* fmt = fmtbase; for (int i = 0; i < pad; ++i) *fmt++ = ' '; if (is_neg) *fmt++ = '-'; for (i = 0; i < iwidth; ++i) *fmt++ = *iw++; if (showdot) { *fmt++ = '.'; fw = fwork; for (i = 0; i < fwidth; ++i) *fmt++ = *fw++; } for (i = 0; i < ewidth; ++i) *fmt++ = *ew++; *fmt = 0; return fmtbase; } idth + showdot + fwidth + ewidtlibg++/src/error.cc 644 473 0 2673 4677700056 7400 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include void default_one_arg_error_handler(const char* msg) { fputs("Error: ", stderr); fputs(msg, stderr); fputs("\n", stderr); abort(); } void default_two_arg_error_handler(const char* kind, const char* msg) { fputs(kind, stderr); fputs(" Error: ", stderr); fputs(msg, stderr); fputs("\n", stderr); abort(); } two_arg_error_handler_t lib_error_handler = default_two_arg_error_handler; two_arg_error_handler_t set_lib_error_handler(two_arg_error_handler_t f) { two_arg_error_handler_t old = lib_error_handler; lib_error_handler = f; return old; } puts("Error: ", stderr); fputs(msg, stderr); fputs("\n", stderr);libg++/src/str.cc 644 473 0 2362 4677700056 7052 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include extern AllocRing _libgxx_fmtq; char* str(const char* s, int width) { int len = strlen(s); int wrksiz = len + width + 1; char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); char* fmt = fmtbase; for (int blanks = width - len; blanks > 0; --blanks) *fmt++ = ' '; while (*s != 0) *fmt++ = *s++; *fmt = 0; return fmtbase; } in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include extern AllocRing _libgxx_fmtq; char* str(const char* s, int width) { int len = strlen(s); int wrkslibg++/src/hash.cc 644 473 0 2677 4677700057 7177 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include /* some useful hash functions */ unsigned int hashpjw(const char* x) // From Dragon book, p436 { unsigned int h = 0; unsigned int g; while (*x != 0) { h = (h << 4) + *x++; if ((g = h & 0xf0000000) != 0) h = (h ^ (g >> 24)) ^ g; } return h; } unsigned int multiplicativehash(int x) { // uses a const close to golden ratio * pow(2,32) return ((unsigned)x) * 2654435767; } unsigned int foldhash(double x) { union { unsigned int i[2]; double d; } u; u.d = x; unsigned int u0 = u.i[0]; unsigned int u1 = u.i[1]; return u0 ^ u1; } char* x) // From Dragon book, p436 { unsigned int h = 0; unslibg++/src/timer.cc 644 473 0 5410 4677700057 7360 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include // Timing functions from Doug Schmidt... /* no such thing as "negative time"! */ #define TIMER_ERROR_VALUE -1.0 // If this does not work on your system, change this to #if 0, and // report the problem #if 1 #ifdef USG extern "C" { #include #include #include } #else #include #endif #ifdef USG static struct tms Old_Time; static struct tms New_Time; #else static struct rusage Old_Time; static struct rusage New_Time; #endif static int Timer_Set = 0; double start_timer() { Timer_Set = 1; #ifdef USG times(&Old_Time); return((double) Old_Time.tms_utime / HZ); #else getrusage(RUSAGE_SELF,&Old_Time); /* set starting process time */ return(Old_Time.ru_utime.tv_sec + (Old_Time.ru_utime.tv_usec / 1000000.0)); #endif } /* Returns process time since Last_Time. If parameter is 0.0, returns time since the Old_Time was set. Returns TIMER_ERROR_VALUE if `start_timer' is not called first. */ double return_elapsed_time(double Last_Time) { if (!Timer_Set) { return(TIMER_ERROR_VALUE); } else { /* get process time */ #ifdef USG times(&New_Time); #else getrusage(RUSAGE_SELF,&New_Time); #endif if (Last_Time == 0.0) { #ifdef USG return((double) (New_Time.tms_utime - Old_Time.tms_utime) / HZ); #else return((New_Time.ru_utime.tv_sec - Old_Time.ru_utime.tv_sec) + ((New_Time.ru_utime.tv_usec - Old_Time.ru_utime.tv_usec) / 1000000.0)); #endif } else { #ifdef USG return((double) New_Time.tms_utime / HZ - Last_Time); #else return((New_Time.ru_utime.tv_sec + (New_Time.ru_utime.tv_usec / 1000000.0)) - Last_Time); #endif } } } #else /* dummy them out */ double start_timer() { return TIMER_ERROR_VALUE; } double return_elapsed_time(double) { return TIMER_ERROR_VALUE; } #endif /* timing stuff */ ((New_Time.ru_utime.tv_usec - Old_Time.ru_utime.tv_usec) / 1000000.0)); #endif } else { #ifdef USG return((double) New_Time.tms_utime / HZ - Last_Time); #else return((New_Time.ru_utime.tv_sec + libg++/src/new.cc 644 473 0 2045 4677700057 7032 #ifndef NO_LIBGXX_MALLOC // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include void* operator new(size_t n) { return malloc (n); } #endif s granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include void* operator new(size_t nlibg++/src/Filebuf.cc 644 473 0 11562 4677700061 7634 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // needed to determine values of O_RDONLY... #ifndef _bufsiz #define _bufsiz(p) ((p)->_bufsiz) #endif void Filebuf::init_streambuf_ptrs() { if (Fp->fp == 0 || Fp->fp->_cnt == 0) { base = gptr = pptr = eptr = 0; // let first over/under flow deal with it } else { base = Fp->fp->_base; eptr = base - 1 + _bufsiz(Fp->fp); gptr = pptr = base; } } int Filebuf::is_open() { return (Fp != 0 && Fp->is_open()); } streambuf* Filebuf::open(const char* name, io_mode m, access_mode a) { if (Fp == 0) Fp = new File(name, m, a); else Fp->open(name, m, a); if (base != 0) Fp->setbuf(eptr-base+1, base); init_streambuf_ptrs(); return this; } streambuf* Filebuf::open(const char* name, const char* m) { if (Fp == 0) Fp = new File(name, m); else Fp->open(name, m); if (base != 0) Fp->setbuf(eptr-base+1, base); init_streambuf_ptrs(); return this; } streambuf* Filebuf::open(int filedesc, io_mode m) { if (Fp == 0) Fp = new File(filedesc, m); else Fp->open(filedesc, m); if (base != 0) Fp->setbuf(eptr-base+1, base); init_streambuf_ptrs(); return this; } streambuf* Filebuf::open(FILE* fileptr) { if (Fp == 0) Fp = new File(fileptr); else Fp->open(fileptr); if (base != 0) Fp->setbuf(eptr-base+1, base); init_streambuf_ptrs(); return this; } Filebuf::Filebuf() : streambuf(), Fp(0) {} Filebuf::Filebuf(const char* filename, io_mode m, access_mode a) : streambuf() { Fp = new File(filename, m, a); init_streambuf_ptrs(); } Filebuf::Filebuf(const char* filename, const char* m) : streambuf() { Fp = new File(filename, m); init_streambuf_ptrs(); } Filebuf::Filebuf(int filedesc, io_mode m) : streambuf() { Fp = new File(filedesc, m); init_streambuf_ptrs(); } Filebuf::Filebuf(FILE* fileptr) : streambuf() { Fp = new File(fileptr); init_streambuf_ptrs(); } int Filebuf::close() { int was = Fp->is_open(); if (was) { overflow(); Fp->close(); } return was; } Filebuf::~Filebuf() { if (Fp != 0) { close(); delete Fp; } } /* The underflow and overflow methods sync the streambuf with the _iobuf ptrs on the way in and out of the read. I believe that this is done in a portable way. */ int Filebuf::underflow() { int ch; if (Fp == 0) return EOF; if (gptr == 0) // stdio _iobuf ptrs not initialized until after 1st read { ch = Fp->fill(); base = Fp->fp->_base; eptr = base - 1 + _bufsiz(Fp->fp); } else { Fp->fp->_ptr = gptr; Fp->fp->_cnt = eptr - gptr + 1; ch = Fp->fill(); } gptr = base; *gptr = ch; if (ch == EOF) pptr = base; else pptr = base + Fp->fp->_cnt + 1; if (Fp->good()) return ch; else { Fp->clear(); return EOF; } } int Filebuf::overflow(int ch) { if (Fp == 0) return EOF; if (Fp->fp->_flag & _IONBF) // handle unbuffered IO specially { if (pptr == 0) // 1st write { if (ch == EOF) return 0; else { Fp->flush(ch); } } else { if (ch == EOF) Fp->flush(); // Probably not necessary else Fp->flush(ch); } } else { if (pptr == 0) // 1st write { if (ch == EOF) return 0; else { Fp->flush(ch); base = Fp->fp->_base; eptr = base - 1 + _bufsiz(Fp->fp); gptr = base; } } else { if (ch != EOF) *pptr++ = ch; Fp->fp->_ptr = pptr; Fp->fp->_cnt = eptr - pptr + 1; Fp->flush(); } pptr = Fp->fp->_ptr; } if (Fp->fail() || Fp->bad()) { Fp->clear(); // this allows recovery from ostream level return EOF; } else return 0; } const char* Filebuf::name() { return Fp->name(); } streambuf* Filebuf::setbuf(char* buf, int buflen, int preload) { if (preload != 0) return 0; // cannot preload, sorry if (Fp != 0) Fp = new File; Fp->setbuf(buflen, buf); init_streambuf_ptrs(); return (Fp->good())? this : 0; } void Filebuf::error() { Fp->error(); } h(); } pptr = Fp->fp->_ptr; } if (Fp->fail() || Fp->bad()) { Fp->clear(); // this allows recovery from ostream level retlibg++/src/Weibell.cc 644 473 0 2214 4677700062 7616 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // // See Simulation, Modelling & Analysis by Law & Kelton, pp259 // // This is the ``polar'' method. // double Weibull::operator()() { return( pow(pBeta * ( - log(1 - pGenerator -> asDouble()) ), pInvAlpha) ); } to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // // See Simulation, Modelling & Analysis by Law & Kelton, pp259 // // This islibg++/src/filebuf.cc 644 473 0 4550 4677700062 7654 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // needed to determine values of O_RDONLY... filebuf::filebuf() :streambuf(), fd(-1), opened(0) {} filebuf::filebuf(int newfd) : streambuf(), fd(newfd), opened(1) {} filebuf::filebuf(int newfd, char* buf, int buflen) : streambuf(buf, buflen), fd(newfd), opened(1) {} int filebuf::is_open() { return opened; } int filebuf::close() { int was = opened; if (was) ::close(fd); opened = 0; return was; } streambuf* filebuf::open(const char* name, open_mode m) { if (opened) return 0; int mode = -1; // any illegal value switch (m) { case input: mode = O_RDONLY; break; case output: mode = O_WRONLY | O_CREAT | O_TRUNC; break; case append: mode = O_APPEND | O_CREAT; break; } fd = ::open(name, mode, 0666); if (opened = (fd >= 0)) { allocate(); return this; } else return 0; } int filebuf::underflow() { if (!opened) return EOF; if (base == 0) allocate(); int nwanted = eptr - base + 1; int nread = ::read(fd, base, nwanted); gptr = base; pptr = base + nread; return (nread == 0)? EOF : int(*gptr); } int filebuf::overflow(int ch) { if (!opened) return EOF; if (base == 0) allocate(); if (ch != EOF) // overflow *must* be called before really full *pptr++ = (char)(ch); int n = pptr - base; if (n > 0) n -= ::write(fd, base, n); pptr = base; return (n ==0)? 0 : EOF; } filebuf::~filebuf() { close(); } se == 0) allocate(); int nwanted = eptr - base + 1; int nread = ::read(fd, base, nwanted); gptr = base; pptr = base + nread; return (nread == libg++/src/ostream.cc 644 473 0 10041 4677700062 7722 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* *** Version 1.2 -- nearly 100% AT&T 1.2 compatible *** */ #include #include #include #include #include ostream::ostream(streambuf* s) : bp(s), state(_good), ownbuf(0) {} ostream::ostream(int sz, char* buf) : state(_good), ownbuf(1) { if (buf == 0) { buf = new char[sz]; bp = new streambuf(buf, sz); bp->setbuf(buf, sz); bp->alloc = 1; } else { bp = new streambuf(buf, sz); bp->alloc = 0; } } ostream::ostream(const char* filename, io_mode m, access_mode a) : state(_good), ownbuf(1) { bp = new Filebuf(filename, m, a); } ostream::ostream(const char* filename, const char* m) : state(_good), ownbuf(1) { bp = new Filebuf(filename, m); } ostream::ostream(int filedesc, io_mode m) : state(_good), ownbuf(1) { bp = new Filebuf(filedesc, m); } ostream::ostream(FILE* fileptr) : state(_good), ownbuf(1) { bp = new Filebuf(fileptr); } ostream::ostream(int filedesc) : state(_good), ownbuf(1) { bp = new filebuf(filedesc); } ostream::ostream(int filedesc, char* buf, int buflen) : state(_good), ownbuf(1) { bp = new filebuf(filedesc, buf, buflen); } ostream::~ostream() { if (ownbuf) delete bp; } ostream& ostream::open(const char* filename, io_mode m, access_mode a) { return failif(bp->open(filename, m, a) == 0); } ostream& ostream::open(const char* filename, const char* m) { return failif(bp->open(filename, m) == 0); } ostream& ostream::open(int filedesc, io_mode m) { return failif(bp->open(filedesc, m) == 0); } ostream& ostream::open(FILE* fileptr) { return failif(bp->open(fileptr) == 0); } ostream& ostream::open(const char* filenam, open_mode m) { return failif(bp->open(filenam, m) == 0); } ostream& ostream::form(const char* fmt...) { va_list args; va_start(args, fmt); char buf[BUFSIZ]; #ifndef HAVE_VPRINTF FILE b; b._flag = _IOWRT|_IOSTRG; b._ptr = buf; b._cnt = BUFSIZ; _doprnt(fmt, args, &b); putc('\0', &b); #else vsprintf(buf, fmt, args); #endif va_end(args); return put(buf); } ostream& ostream::operator<<(short n) { return put(itoa(long(n))); } ostream& ostream::operator<<(unsigned short n) { return put(itoa((unsigned long)(n))); } ostream& ostream::operator<<(int n) { return put(itoa(long(n))); } ostream& ostream::operator<<(unsigned int n) { return put(itoa((unsigned long)(n))); } ostream& ostream::operator<<(long n) { return put(itoa(n)); } ostream& ostream::operator<<(unsigned long n) { return put(itoa(n)); } #ifdef __GNUG__ ostream& ostream::operator<<(long long n) { return put(itoa(n)); } ostream& ostream::operator<<(unsigned long long n) { return put(itoa(n)); } #endif ostream& ostream::operator<<(float n) { return put(dtoa(double(n))); } ostream& ostream::operator<<(double n) { return put(dtoa(n)); } const char* ostream::name() { return bp->name(); } void ostream::error() { bp->error(); } #ifndef DEFAULT_filebuf ostream cerr(stderr); ostream cout(stdout); #else static char cerrbuf[1]; static char coutbuf[BUFSIZE]; ostream cerr(2, cerrbuf, 1); ostream cout(1, coutbuf, BUFSIZE); #endif rator<<(unsigned long long n) { return put(itoa(n)); } #endif ostream& ostream::operator<<(float n) { return put(dtoa(double(n))); } ostream& ostream::operator<<(double n) { return put(dtoa(n)); } const char* ostream::name() { return bp->name(); } void ostream::error() { bp->error(); } #ifndef DEFAULT_filebuf ostream cerr(stderr); ostream cout(stdout); #else static char cerrbuf[1]; static char coutbuf[BUFSIZE]; ostream cerr(2, cerrbuf, 1); ostream colibg++/src/HyperGeo.cc 644 473 0 2147 4677700062 7762 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double HyperGeometric::operator()() { double d = (pGenerator -> asDouble() > pP) ? (1.0 - pP) : (pP); return(-pMean * log(pGenerator -> asDouble()) / (2.0 * d) ); } A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double HyperGeometric::operator()() { double d = (pGenerator -> asDlibg++/src/Geometric.cc 644 473 0 2111 4677700062 10145 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Geometric::operator()() { int samples; for (samples = 1; pGenerator -> asDouble() < pMean; samples++); return((double) samples); } NU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Geometric::operator()() { int samples; for (samples = 1; pGenelibg++/src/Uniform.cc 644 473 0 2011 4677700062 7645 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Uniform::operator()() { return( pLow + delta * pGenerator -> asDouble() ); } tribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Uniform::operator()() { return( pLow + delta * pGenerator -> asDoubllibg++/src/Erlang.cc 644 473 0 2115 4677700063 7444 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Erlang::operator()() { double prod = 1.0; for (int i = 0; i < k; i++) { prod *= pGenerator -> asDouble(); } return(-log(prod)/a); } C General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Erlang::operator()() { double prod = 1.0; for (int i = 0; i < k;libg++/src/DiscUnif.cc 644 473 0 2102 4677700063 7734 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double DiscreteUniform::operator()() { long tmp = long(floor(delta * pGenerator -> asDouble())); return( double(pLow + tmp) ); } n the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double DiscreteUniform::operator()() { long tmp = long(floor(delta libg++/src/Normal.cc 644 473 0 3550 4677700063 7470 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include // // See Simulation, Modelling & Analysis by Law & Kelton, pp259 // // This is the ``polar'' method. // double Normal::operator()() { if (haveCachedNormal == 1) { haveCachedNormal = 0; return(cachedNormal * pStdDev + pMean ); } else { for(;;) { double u1 = pGenerator -> asDouble(); double u2 = pGenerator -> asDouble(); double v1 = 2 * u1 - 1; double v2 = 2 * u2 - 1; double w = (v1 * v1) + (v2 * v2); // // We actually generate two IID normal distribution variables. // We cache the one & return the other. // if (w <= 1) { double y = sqrt( (-2 * log(w)) / w); double x1 = v1 * y; double x2 = v2 * y; haveCachedNormal = 1; cachedNormal = x2; return(x1 * pStdDev + pMean); } } } } #include // // See Simulation, Modelling & Analysis by Law & Kelton, pp260 // // double LogNormal::operator()() { return( pow(M_E, this->Normal::operator()() ) ); } 2 * v2); // // We actually generate two IID normal distribution variables. // We cache the one & return the other. // if (w <= 1) { doublelibg++/src/Poisson.cc 644 473 0 2224 4677700063 7667 /* Copyright (C) 1988 Free Software Foundation written by Dirk Grunwald (grunwald@cs.uiuc.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Poisson::operator()() { double bound = exp(-1.0 * pMean); int count = 0; for (double product = 1.0; product >= bound; product *= pGenerator -> asDouble()) { count++; } return(count - 1); } been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include double Poisson::operator()() { double bound = exp(-1.0 * pMean); int clibg++/src/istream.cc 644 473 0 23021 4677700064 7720 // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* *** Version 1.2 -- nearly 100% AT&T 1.2 compatible *** */ #include #include #include #include #include istream::istream(streambuf* s, int sk, ostream* t) : bp(s), state(_good), skipws(sk), tied_to(t), ownbuf(0) {} istream::istream(int sz, char* buf, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new streambuf; if (buf == 0) { bp->alloc = 1; buf = new char[sz]; } else bp->alloc = 0; bp->setbuf(buf, sz, sz); } istream::~istream() { if (ownbuf) delete bp; } istream::istream(const char* filename, io_mode m, access_mode a, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new Filebuf(filename, m, a); } istream::istream(const char* filename, const char* m, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new Filebuf(filename, m); } istream::istream(int filedesc, io_mode m, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new Filebuf(filedesc, m); } istream::istream(FILE* fileptr, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new Filebuf(fileptr); } istream::istream(int filedesc, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new filebuf(filedesc); } istream::istream(int filedesc, char* buf, int buflen, int sk, ostream* t) : state(_good), skipws(sk), tied_to(t), ownbuf(1) { bp = new filebuf(filedesc, buf, buflen); } istream& istream::open(const char* filename, io_mode m, access_mode a) { return failif(bp->open(filename, m, a) == 0); } istream& istream::open(const char* filename, const char* m) { return failif(bp->open(filename, m) == 0); } istream& istream::open(int filedesc, io_mode m) { return failif(bp->open(filedesc, m) == 0); } istream& istream::open(FILE* fileptr) { return failif(bp->open(fileptr) == 0); } istream& istream::open(const char* filenam, open_mode m) { return failif(bp->open(filenam, m) == 0); } istream& istream::get(char& c) { if (good()) { if(tied_to != 0) tied_to->flush(); int ch = bp->sgetc(); if (ch == EOF) set(_eof); else { c = ch; bp->stossc(); } } return *this; } istream& istream::operator >> (whitespace&) { if (good()) { int ch; if(tied_to != 0) tied_to->flush(); while (((ch = bp->sgetc()) != EOF) && isspace(ch)) bp->stossc(); if (ch == EOF) set(_eof); } return *this; } istream& istream::operator >> (char& c) { if (skipws) (*this >> WS); return get(c); } istream& istream::get(char* s, int n, char terminator) { if (!readable()) { set(_fail); return *this; } char ch = 0; char* start = s; if (--n > 0 && get(ch)) { if (ch == terminator) unget(ch); else { *s++ = ch; --n; while (n-- > 0 && get(ch)) { if (ch == terminator) { unget(ch); break; } else *s++ = ch; } } } *s = 0; if (s != start) clear(); return *this; } istream& istream::operator >> (char* s) { if (!readable() || s == 0) { set(_fail); return *this; } if (skipws && !(*this >> WS)) return *this; char ch; char* start = s; if (get(ch)) { *s++ = ch; while (get(ch)) { if (isspace(ch)) { unget(ch); break; } else *s++ = ch; } } *s = 0; if (s != start) clear(); return *this; } istream& istream::getline(char* s, int n, char terminator) { if (!readable()) { set(_fail); return *this; } char* start = s; char ch; while (--n > 0 && get(ch) && ((*s++ = ch) != terminator)); *s = 0; if (s != start) clear(); return *this; } // from Doug Schmidt // This should probably be a page size.... #define CHUNK_SIZE 512 /* Reads an arbitrarily long input line terminated by a user-specified TERMINATOR. Super-nifty trick using recursion avoids unnecessary calls to NEW! */ char *istream::readline (int chunk_number, char terminator) { char buf[CHUNK_SIZE]; register char *bufptr = buf; register char *ptr; char ch; int continu; while ((continu = !!get(ch)) && ch != terminator) /* fill the current buffer */ { *bufptr++ = ch; if (bufptr - buf >= CHUNK_SIZE) /* prepend remainder to ptr buffer */ { if (ptr = readline (chunk_number + 1, terminator)) for (; bufptr != buf; *--ptr = *--bufptr); return ptr; } } if (!continu && bufptr == buf) return NULL; int size = (chunk_number * CHUNK_SIZE + bufptr - buf) + 1; if (ptr = new char[size]) { for (*(ptr += (size - 1)) = '\0'; bufptr != buf; *--ptr = *--bufptr) ; return ptr; } else return NULL; } /* Reads an arbitrarily long input line terminated by TERMINATOR. This routine allocates its own memory, so the user should only supply the address of a (char *). */ istream& istream::gets(char **s, char terminator) { return failif(!readable() || !(*s = readline (0, terminator))); } istream& istream::operator >> (long& y) { if (!readable()) { set(_bad); return *this; } int got_one = 0; char sgn = 0; char ch; y = 0; if (skipws) *this >> WS; if (!good()) { set(_bad); return *this; } while (get(ch)) { if (ch == '-') { if (sgn == 0) sgn = '-'; else break; } else if (ch >= '0' && ch <= '9') y = y * 10 + ((got_one = ch) - '0'); else break; } if (good()) unget(ch); if (!got_one) set(_bad); else clear(); if (sgn == '-') y = -y; return *this; } istream& istream::operator >> (unsigned long& y) { if (!readable()) { set(_bad); return *this; } int got_one = 0; char ch; y = 0; if (skipws) *this >> WS; if (!good()) while (get(ch)) { if (ch >= '0' && ch <= '9') y = y * 10 + ((got_one = ch) - '0'); else break; } if (good()) unget(ch); if (!got_one) set(_bad); else clear(); return *this; } /* for input to a double, we must trust atof (cannot even use the better strtod since it is not universally supported). So guaranteed legal chars are gathered up into an obstack. The only possible, undiagnosable error is that the input number might give a floating overflow or underflow inside atof. I know of no way to avoid this */ extern Obstack _libgxx_io_ob; istream& istream::operator >> (double & y) { if (!readable()) { set(_bad); return *this; } char seenint = 0; char seendec = 0; char seenexp = 0; char seensgn = 0; char seene = 0; char seenexpsgn = 0; char seendot = 0; char ch; if (skipws) *this >> WS; if (!good()) { set(_bad); return *this; } while (get(ch)) { if (ch == '-' || ch == '+') { if (seene && !seenexpsgn) _libgxx_io_ob.grow(seenexpsgn = ch); else if (!seensgn && !seenint) _libgxx_io_ob.grow(seensgn = ch); else break; } else if (ch == '.' && !seendot) { _libgxx_io_ob.grow(seendot = ch); } else if ((ch == 'e' || ch == 'E') && !seene) { _libgxx_io_ob.grow(seene = ch); } else if (ch >= '0' && ch <= '9') { _libgxx_io_ob.grow(ch); if (seene) seenexp = ch; else if (seendot) seendec = ch; else seenint = ch; } else break; } char* str = (char *) _libgxx_io_ob.finish(0); if (good()) unget(ch); if ((seenint || seendec) && (!seene || seenexp)) y = atof(str); else set(_bad); _libgxx_io_ob.free(str); return *this; } istream& istream::operator >> (int& y) { long l; (*this >> l); y = int(l); return *this; } istream& istream:: operator >> (unsigned int& y) { long l; (*this >> l); y = (unsigned int)(l); return *this; } istream& istream:: operator >> (short& y) { long l; (*this >> l); y = short(l); return *this; } istream& istream:: operator >> (unsigned short& y) { long l; (*this >> l); y = (unsigned short)(l); return *this; } istream& istream:: operator >> (float& y) { double d; (*this >> d); y = float(d); return *this; } const char* istream::name() { return bp->name(); } void istream::error() { bp->error(); } ostream* istream::tie(ostream* s) { ostream* was = tied_to; tied_to = s; return was; } void istream::_flush() { if(tied_to != 0) tied_to->flush(); } //-------------------------------------------------------------- extern ostream cout; #ifndef DEFAULT_filebuf istream cin(stdin, 1, &cout); #else static char cinbuf[BUFSIZE]; istream cin (0, cinbuf, BUFSIZE, 1, &cout); #endif whitespace WS; *this; } const char* istream::name() { return bp->name(); } void istream::error() { bp->error(); } ostream* istream::tie(ostream* s) { ostream* was = tied_to; tied_to = s; return was; } void istream::_flush() { if(tied_to != 0) tied_to->flush(); } //-------------------------------------------------------------- extern ostream cout; #ifndef DEFAULT_filebuf istream cin(stdin, 1, &cout); #else static char cinbuf[BUFSIZE]; istream cin (0, cinbuf, BUFSIZE, 1, &cout); #endiflibg++/src/EH2.c 644 473 0 452 4677700064 6432 /* Unhandled exceptions cause the program to abort. Argument FILENAME is the name of the file that caught the exception. Argument LINENO is the line number at which the exception was caught. */ extern volatile void abort(); void __unhandled_exception (char *filename, int lineno) { abort (); } --------------------------------------------- extern ostream cout; #ifndef DEFAULT_filebuf istream cin(stdin, 1, &cout); #else static char cinbuf[BUFSIZE]; istream cin (0, cinbuf, BUFSIZE, 1, &cout); #endiflibg++/src/delete.cc 644 473 0 2041 4677700064 7475 #ifndef NO_LIBGXX_MALLOC // This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1989 Free Software Foundation written by Doug Lea (dl@oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include void operator delete(void* ptr) { free (ptr); } #endif ne is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include void operator delete(void*libg++/src/libgxx_ob.cc 644 473 0 2000 4677700055 10203 /* Copyright (C) 1990 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include // Obstacks are used as an easy way to allocate enough space // for various builtin input operations Obstack _libgxx_io_ob; libg++/proto-kit/Makefile 644 473 0 31074 4677700065 10556 # Makefile for libg++ prototype files # Copyright (C) 1989 Free Software Foundation, Inc. # written by Carl Staelin #This file is part of GNU libg++. #GNU libg++ 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 1, or (at your option) #any later version. #GNU libg++ 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 GNU libg++; see the file COPYING. If not, write to #the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. #****************************************************************************** # This GNUmakefile is useful for large and complex projects which involve # both G++ library prototypes, and prototypes added by the user(s). It # is assumed that certain conventions are followed. # # 1) each object has its own source and header files. For example class W # would have W.h and W.cc # # 2) each prototype object has its own source and header files (W.hP and W.ccP) # # 3) object header files are contained in directory $(IDIR) (for Include # DIRectory) # # 4) object source files are contained in the current directory # # 5) prototype instantiations are contained in $(PC) (for Prototype C++ # directory) # # 6) user prototype files (both header and source) are contained in $(IPP) # # 7) non-class code is contained in .h and .cc files, which live in $(IDIR) # and the current directory respectively # # 8) for each class W, W_p is defined as a type which is the pointer to W # # *) as an extra, I have added the convention that whenever a W.cc file # is being compiled, the macro _W_cc is defined. This is useful # particularly for conditional parts of header files (for example, # W.h could have ifdef _W_cc ... # # The makefile works in the following manner: the source dependencies are # contained in .Makefile.S_DEP, while the (machine generated) object # dependencies are contained in .Makefile.O_DEP. The types needed by # the program are defined by several variables, and the makefile generates # the necessary dependencies (both source and object) from those variables. # # -- Carl Staelin # staelin@princeton.edu #****************************************************************************** #****************************************************************************** # standard Makefile definitions comma := , space := $(empty) $(empty) tab := $(empty) $(empty) #****************************************************************************** # Basic definitions # GNU directories GNULIBDIR=/usr/local/lib GNUIDIR = $(GNULIBDIR)/g++-include # the g++ prototypes... LPP = $(GNUIDIR) PC = ../libg++ # the user's prototypes... IPP = ../proto # the include directory IDIR = ../include # the G++ include directories (for use in C++-FLAGS) IDIRS = -I$(IDIR) -I$(PC) -I$(GNUIDIR) # the directories where the libraries live (for use in C++-FLAGS) LDIRS = -L$(PC) #****************************************************************************** # standard function (and associated variables) definitions C++ = g++ C++FLAGS = -pipe $(IDIRS) GENCLASS = genclass.extnsn PREPEND = prepend-header CONVERT_DEPENDENCIES = convert-dependencies #****************************************************************************** # implicit rules %.o : %.cc $(C++) $(C++FLAGS) \ -D$(strip $(subst .,_, _$(basename $(@F))_cc)) \ -c -o $@ $(@D)$(basename $(@F)).cc #****************************************************************************** # ipcress (object code) library definitions PROTOLIBDESIGNATOR = p PROTOLIB = $(PC)/lib$(PROTOLIBDESIGNATOR).a LIBS = -l$(PROTOLIBDESIGNATOR) #****************************************************************************** # types which do not have a class associated with them. For example # int, and l_u_int (long unsigned int) BASIC_TYPES = \ int \ l_u_int #****************************************************************************** # User types -- these are the user's classes TYPES = \ User_class_1 \ User_class_2 \ User_class_3 #****************************************************************************** # User files HEADER_FILES = \ include \ utils SOURCE_FILES = \ utils #****************************************************************************** # source files... HEADERS = $(addprefix $(IDIR)/, $(addsuffix .h, $(TYPES) $(HEADER_FILES))) SOURCES = $(addsuffix .cc, $(TYPES) $(SOURCE_FILES)) OBJECTS = $(addsuffix .o, $(TYPES) $(SOURCE_FILES)) #****************************************************************************** # libg++ prototype instantiations LIB_PROTO_FILES = \ User_class_3_p.Set \ User_class_3_p.AVLSet \ User_class_1_p.SLList \ User_class_1User_proto_1_p.Set \ l_u_int.DLList \ l_u_int.User_class_2User_proto_1_p.Map \ l_u_int.User_class_2User_proto_1_p.AVLMap LIB_PROTO_HEADER_FILES = \ User_class_1.defs \ User_class_1_p.defs \ User_class_3.defs \ User_class_3_p.defs \ User_class_1User_proto_1.defs \ User_class_1User_proto_1_p.defs \ l_u_int.defs LIB_PROTO_HEADERS = $(addprefix $(PC)/, $(addsuffix .h, $(LIB_PROTO_FILES) $(LIB_PROTO_HEADER_FILES))) LIB_PROTO_SOURCES = $(addprefix $(PC)/, $(addsuffix .cc, $(LIB_PROTO_FILES))) LIB_PROTO_OBJECTS = $(addsuffix .o, $(basename $(LIB_PROTO_SOURCES))) #****************************************************************************** # User prototype instantiations PROTO_FILES = \ User_class_1.User_proto_1 \ User_class_2.User_proto_1 # some user prototypes have just a header class definition file (.h) PROTO_HEADER_FILES = PROTO_HEADERS = $(addprefix $(PC)/, $(addsuffix .h, \ $(PROTO_FILES) $(PROTO_HEADER_FILES))) PROTO_SOURCES = $(addprefix $(PC)/, $(addsuffix .cc, $(PROTO_FILES))) PROTO_OBJECTS = $(addsuffix .o, $(basename $(PROTO_SOURCES))) PROTO_TYPE_SOURCES = $(addsuffix P, $(PROTO_HEADERS) $(PROTO_SOURCES)) #***************************************************************************** # program(s) to be made program : $(OBJECTS) $(PROTOLIB) program.o $(C++) $(C++FLAGS) -o program program.o $(OBJECTS) $(LDIRS) $(LIBS) #****************************************************************************** # various cleanup stuff... .PHONY : rmback clean realclean rmback : cd .. ; rm -f proto/*~ include/*~ src/*~ clean : rmback rm -f $(OBJECTS) $(PROTOLIB) $(LIB_PROTO_OBJECTS) $(PROTO_OBJECTS) realclean : clean rm -f $(LIB_PROTO_SOURCES) $(PROTO_SOURCES) $(LIB_PROTO_HEADERS) $(PROTO_HEADERS) #****************************************************************************** # library dependencies $(PROTOLIB) : $(LIB_PROTO_OBJECTS) $(PROTO_OBJECTS) rm -f $(PROTOLIB) ; \ ar q $(PROTOLIB) $(LIB_PROTO_OBJECTS) $(PROTO_OBJECTS) ; \ ranlib $(PROTOLIB) #****************************************************************************** # "functions" for creating library source code from prototypes components = $(subst .,$(space),$(notdir $(basename $@))) ifdef_filename = $(subst .,_,$(notdir $(basename $@))) first-parameter = $(word 1, $(components)) second-parameter = $(word 2, $(three-parts-q)) generic-type = $(word $(words $(components)), $(components)) debug.type.gen.h : @ echo '$$(components) = $(components)' ; @ echo '$$(words $$(components)) = $(words $(components))' ; @ echo '$$(word $$(words $$(components)), $(components)) = $(word $(words $(components)), $(components))' ; # are there three parts to the generic file name? three-parts-q = $(subst 3,$(components),$(filter 3, $(words $(components)))) # is the first generic parameter a val parameter? first-val-q = $(filter %_p, $(first-parameter)) $(filter-out %_p, $(foreach basic-type, $(BASIC_TYPES), $(filter $(basic-type), $(first-parameter)))) # # is the second paramter a val parameter? (if there is a second parameter) # - if there is a second parameter then there are two copies of the second # parameter. # - if the parameter is a "val" type, then there is one copy of the type # - if the parameter is a "ref" type, then do nothing. # # hence the cases are: # - there exists a second type # - it has type "val": there are three words on the output string # - it has type "ref": there are two words on the output string # - there isn't a second type: there are 0 or 1 words on the output string # second-val-q = $(foreach offset, 1 2, $(second-parameter)) \ $(filter %_p, $(second-parameter)) $(filter-out %_p, $(foreach basic-type, $(BASIC_TYPES), $(filter $(basic-type), $(second-parameter)))) define make-defs-file ( \ echo '#ifndef $(patsubst %, _%_h', $(ifdef_filename)) ; \ echo '#define $(patsubst %, _%_h', $(ifdef_filename)) ; \ echo $(patsubst %_p, '#include "%.defs.h"', $(first-parameter)) ; \ echo '#define $(patsubst %_p, %_pEQ(a$(comma)b), $(first-parameter)) \ $(patsubst %_p, %EQ(*(a)$(comma)*(b))', $(first-parameter)) ; \ echo '#define $(patsubst %_p, %_pLE(a$(comma)b), $(first-parameter)) \ $(patsubst %_p, %LE(*(a)$(comma)*(b))', $(first-parameter)) ; \ echo '#define $(patsubst %_p, %_pCMP(a$(comma)b), $(first-parameter)) \ $(patsubst %_p, %CMP(*(a)$(comma)*(b))', $(first-parameter)) ; \ echo '#define $(patsubst %_p, %_pHASH(x), $(first-parameter)) \ $(patsubst %_p, %HASH(*(x))', $(first-parameter)) ; \ echo '#endif $(patsubst %, _%_h', $(ifdef_filename)) ; \ ) > $@ endef define make-proto-file $(GENCLASS) \ $(dir $<) \ $(dir $@) \ $(suffix $@) \ $(patsubst %,-2, $(word 1, $(three-parts-q))) \ $(first-parameter) \ $(patsubst %,val, $(first-val-q)) \ $(patsubst %,ref,$(filter 0, $(words $(first-val-q)))) \ $(second-parameter) \ $(patsubst %,val, $(filter 3, $(words $(second-val-q)))) \ $(patsubst %,ref, $(filter 2, $(words $(second-val-q)))) \ $(generic-type) endef define prepend-proto-includes $(PREPEND) \ $(addsuffix .h, $(basename $@)) \ '#include "include.h"' \ $(patsubst %, '#include "%.h"', $(foreach proto, $(TYPES) $(LIB_PROTO_FILES) $(LIB_PROTO_HEADER_FILES) $(PROTO_FILES) $(PROTO_HEADER_FILES), $(patsubst %, $(proto), $(filter $(subst .,,$(proto)), $(patsubst %_p, %, $(first-parameter) $(second-parameter)))))) endef ifeq (TRUE,FALSE) endif #****************************************************************************** # libg++ prototype dependencies $(addprefix $(PC)/, $(addsuffix .h, $(filter-out char_p.defs, \ $(filter %_p.defs, $(LIB_PROTO_HEADER_FILES))))) : echo creating $@ ; \ $(make-defs-file) ; lib_proto_intermediate_sources = \ $(filter-out %_p.defs.h, $(LIB_PROTO_HEADERS) $(LIB_PROTO_SOURCES)) \ $(addprefix $(PC)/, $(addsuffix .h, char_p.defs)) lib_type_and_suffix_list = $(sort $(join $(suffix $(basename $(lib_proto_intermediate_sources))), $(addprefix ., $(suffix $(lib_proto_intermediate_sources))))) #****************************************************************************** # user prototype dependencies proto_intermediate_sources = \ $(PROTO_HEADERS) \ $(PROTO_SOURCES) type_and_suffix_list = $(sort $(join $(suffix $(basename $(proto_intermediate_sources))), $(addprefix ., $(suffix $(proto_intermediate_sources))))) #****************************************************************************** # generate machine generated dependencies H_FILES = $(HEADERS) $(LIB_PROTO_HEADERS) $(PROTO_HEADERS) CC_FILES = $(SOURCES) $(LIB_PROTO_SOURCES) $(PROTO_SOURCES) DEPENDENCIES = $(addsuffix .d, $(basename $(CC_FILES))) $(addsuffix .d, $(basename $(CC_FILES))) : %.d : %.cc $(C++) -M $(C++FLAGS) $< | \ $(CONVERT_DEPENDENCIES) $(dir $@) | \ sort -u | sed 's?$(LPP)?$$(LPP)?g' | \ sed 's?$(PC)?$$(PC)?g' > $@ ; $(DEPENDENCIES) : $(H_FILES) .PHONY : dependencies source-dependencies object-dependencies dependencies : source-dependencies object-dependencies object-dependencies : $(DEPENDENCIES) @echo making object dependencies ; \ cat $(sort $(DEPENDENCIES)) > .Makefile.O_DEP ; source-dependencies : @ echo making source dependencies... ; \ ( \ $(foreach type, $(lib_type_and_suffix_list), echo '%.$(type) : $$(LPP)/$(type)P'; echo '$(tab)$$(make-proto-file) ; $(patsubst %, $$(prepend-proto-includes);, $(filter h, $(suffix $(type))))'; echo ; ) \ $(foreach type, $(type_and_suffix_list), echo '%.$(type) : $$(IPP)/$(type)P'; echo '$(tab)$$(make-proto-file) ; $(patsubst %, $$(prepend-proto-includes);, $(filter h, $(suffix $(type))))'; echo;) \ ) > .Makefile.S_DEP ; #****************************************************************************** # include machine generated dependencies include .Makefile.S_DEP include .Makefile.O_DEP (tab)$$(make-proto-file) ; $(patsubst %, $$(prepend-proto-includes);, $(filter h, $(suffix $(type))))'; echo ; ) \ $(foreach type, $(type_and_suffix_list), echo '%.$(type) : $$(IPP)/$(type)P'; echo '$(tab)$$(make-proto-file) ; $(patsubst %, $$(prepend-proto-includes);, $(filter h, $(suffix $(type))))'; echo;) \ ) > .Makefile.S_DEP ; #****************************************************************************** # include machine generated deplibg++/proto-kit/convert-depend 755 473 0 420 4677700065 11710 #!/bin/sh if { test $# = 1; } then directory=$1; shift else directory=; fi if { test ${directory} = ./ ; } then directory= fi sed 's/\\//g' | awk '{i = 1; if (NR==1) {file = $1; i = 3;} \ for ( ; i <=NF ; i++) printf "%s%s : %s\n", "'${directory}'", file, $i} ' ake-proto-file) ; $(patsubst %, $$(prepend-proto-includes);, $(filter h, $(suffix $(type))))'; echo;) \ ) > .Makefile.S_DEP ; #****************************************************************************** # include machine generated deplibg++/proto-kit/genclass.extns 755 473 0 2752 4677700074 11764 #!/bin/sh # shell script for generating classes from prototypes # # usage: genclass protodir cdir extension [-2] type1 {ref, val} # [type2 {ref, val}] proto # # modified by Carl Staelin to generate a single file (either the .h or # the .cc file, but not both in the same pass). This is useful when # there are user prototypes which are volatile, and whose implementations # are being debugged (less code is recompiled if the .h file is touched) # search in standard g++ prototype directory & in current #PROTODIR=/usr/local/lib/g++-proto PROTODIR=$1; shift; CURRENTDIR=`pwd` #OUTDIR=`pwd` OUTDIR=$1; shift; EXTNSN=$1; shift; #debug #echo protodir is $PROTODIR #echo outdir is $OUTDIR N="" T2="" T2ACC="" case $1 in -2) N="2"; shift;; *) ;; esac T1=$1 case $2 in ref) T1ACC="\&";; val) T1ACC=" ";; *) echo "Must specify type1 access: ref or val"; exit 1;; esac case $N in 2) T2=$3; case $4 in ref) T2ACC="\&";; val) T2ACC=" ";; *) echo "Must specify type2 access: ref or val"; exit 1;; esac; CLASS=$5;; *) CLASS=$3;; esac # .h and .cc parts done separately in case only a .h SRC=$CLASS.$EXTNSN.proto OUT=$OUTDIR/$T1$T2$CLASS.$EXTNSN #debug #echo h source file is $SRC #echo h outfile is $OUT if test -f $CURRENTDIR/$SRC then SRC=$CURRENTDIR/$SRC elif test -f $PROTODIR/$SRC then SRC=$PROTODIR/$SRC else echo "genclass: $SRC: no such file"; exit 1; fi sed < $SRC > $OUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" ccess: ref or val"; exlibg++/proto-kit/prepend-header 755 473 0 555 4677700074 11667 #!/bin/csh -f # usage: prepend file string1 ... stringn # if ($#argv < 2) then echo incorrect usage ; exit 1; endif set FILE = $1; shift; set TMP = /tmp/prepend.$$ if (!(-r $FILE)) then echo file $FILE not found ; exit 1; endif set DUMMY = 0 while ($DUMMY < $#argv) @ DUMMY++ echo "$argv[$DUMMY]" >>& $TMP end cat $FILE >> $TMP cp $TMP $FILE rm -f $TMP uch file"; exit 1; fi sed < $SRC > $OUT -e "s//$T1/g" -e "s//$T1$T1ACC/g" -e "s//$T2/g" -e "s//$T2$T2ACC/g" ccess: ref or val"; ex