diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /gnu/lib |
initial import of NetBSD tree
Diffstat (limited to 'gnu/lib')
273 files changed, 59755 insertions, 0 deletions
diff --git a/gnu/lib/Makefile b/gnu/lib/Makefile new file mode 100644 index 00000000000..7bed40e0f3a --- /dev/null +++ b/gnu/lib/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.7 1995/04/23 07:50:21 cgd Exp $ + +SUBDIR+= libmalloc +.if (${MACHINE_ARCH} != "alpha") +SUBDIR+= libg++ +.endif + +.include <bsd.subdir.mk> diff --git a/gnu/lib/libg++/COPYING b/gnu/lib/libg++/COPYING new file mode 100644 index 00000000000..9a170375811 --- /dev/null +++ b/gnu/lib/libg++/COPYING @@ -0,0 +1,249 @@ + + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 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. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gnu/lib/libg++/Makefile b/gnu/lib/libg++/Makefile new file mode 100644 index 00000000000..0092c731a02 --- /dev/null +++ b/gnu/lib/libg++/Makefile @@ -0,0 +1,27 @@ +# $Id: Makefile,v 1.1 1995/10/18 08:38:05 deraadt Exp $ + +SUBDIR= libg++ genclass + +INCLUDEDIRS= iostream libg++ g++-include + +beforeinstall: + install -d -o ${BINOWN} -g ${BINGRP} -m 755 \ + ${DESTDIR}/usr/include/g++ + install -d -o ${BINOWN} -g ${BINGRP} -m 755 \ + ${DESTDIR}/usr/include/g++/gen + @-for i in ${INCLUDEDIRS}; do \ + echo installing includes from $$i ; \ + (cd $$i; for j in *.[ih]; do \ + cmp -s $$j ${DESTDIR}/usr/include/g++/$$j || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 644 $$j \ + ${DESTDIR}/usr/include/g++/$$j; \ + done); \ + done + @echo installing includes from g++-include/gen + @(cd g++-include/gen ; for j in *.*P; do \ + cmp -s $$j ${DESTDIR}/usr/include/g++/gen/$$j || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 $$j \ + ${DESTDIR}/usr/include/g++/gen/$$j; \ + done) + +.include <bsd.subdir.mk> diff --git a/gnu/lib/libg++/VERSION b/gnu/lib/libg++/VERSION new file mode 100644 index 00000000000..22c1fccec44 --- /dev/null +++ b/gnu/lib/libg++/VERSION @@ -0,0 +1,3 @@ +libg++ version 2.4 + +complete, unmodified libg++ sources are available from prep.ai.mit.edu. diff --git a/gnu/lib/libg++/g++-include/ACG.cc b/gnu/lib/libg++/g++-include/ACG.cc new file mode 100644 index 00000000000..27e7aa22564 --- /dev/null +++ b/gnu/lib/libg++/g++-include/ACG.cc @@ -0,0 +1,291 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#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; +static 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 < 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); +} diff --git a/gnu/lib/libg++/g++-include/ACG.h b/gnu/lib/libg++/g++-include/ACG.h new file mode 100644 index 00000000000..f78a54163a9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/ACG.h @@ -0,0 +1,71 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: ACG.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ +*/ + +#ifndef _ACG_h +#define _ACG_h 1 + +#include <RNG.h> +#include <math.h> +#ifdef __GNUG__ +#pragma interface +#endif + +// +// 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 diff --git a/gnu/lib/libg++/g++-include/AllocRing.cc b/gnu/lib/libg++/g++-include/AllocRing.cc new file mode 100644 index 00000000000..5be1ff06f41 --- /dev/null +++ b/gnu/lib/libg++/g++-include/AllocRing.cc @@ -0,0 +1,110 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <AllocRing.h> +#include <new.h> + +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 >= int(size) && + nodes[current].sz < int(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; +} diff --git a/gnu/lib/libg++/g++-include/AllocRing.h b/gnu/lib/libg++/g++-include/AllocRing.h new file mode 100644 index 00000000000..6a28b15b011 --- /dev/null +++ b/gnu/lib/libg++/g++-include/AllocRing.h @@ -0,0 +1,63 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: AllocRing.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ +*/ + +#ifndef _AllocRing_h +#ifdef __GNUG__ +#pragma interface +#endif +#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 diff --git a/gnu/lib/libg++/g++-include/Binomial.cc b/gnu/lib/libg++/g++-include/Binomial.cc new file mode 100644 index 00000000000..7166e55927c --- /dev/null +++ b/gnu/lib/libg++/g++-include/Binomial.cc @@ -0,0 +1,34 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Binomial.h> + +double Binomial::operator()() +{ + int s = 0; + for (int i = 0; i < pN; i++) { + if (pGenerator -> asDouble() < pU) { + s++; + } + } + return(double(s)); +} + diff --git a/gnu/lib/libg++/g++-include/Binomial.h b/gnu/lib/libg++/g++-include/Binomial.h new file mode 100644 index 00000000000..097f9ee027b --- /dev/null +++ b/gnu/lib/libg++/g++-include/Binomial.h @@ -0,0 +1,58 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Binomial.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _Binomial_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Binomial_h 1 + +#include <Random.h> + +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()(); + +}; + + +inline Binomial::Binomial(int n, double u, RNG *gen) +: Random(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 diff --git a/gnu/lib/libg++/g++-include/BitSet.cc b/gnu/lib/libg++/g++-include/BitSet.cc new file mode 100644 index 00000000000..7255f3d6bc1 --- /dev/null +++ b/gnu/lib/libg++/g++-include/BitSet.cc @@ -0,0 +1,1000 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + BitSet class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <BitSet.h> +#include <std.h> +#include <limits.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include <string.h> +#include <strstream.h> + +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 << (sizeof(short)*CHAR_BIT - 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]; + memset(rep, 0, 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) + memcpy(rep->s, src, srclen * sizeof(short)); + // BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus + if (rep->virt) + memset(&rep->s[srclen], ONES, (newlen - 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); + memcpy(rep->s, old->s, old->len * sizeof(short)); + rep->virt = old->virt; + // BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus + if (rep->virt) + memset(&rep->s[old->len], ONES, (newlen - old->len) * sizeof(short)); + 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; + + memcpy(rep->s, src->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) +{ + 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; + if (xl<=yl) + { + if (memcmp((void*)xs, (void*)ys, xl * sizeof(short))) + return 0; + for (register int i=xl; i<yl; i++) + if (ys[i]) + return 0; + return 1; + } + else + { + if (memcmp((void*)xs, (void*)ys, yl * sizeof(short))) + return 0; + for (register int i=yl; i<xl; i++) + if (xs[i]) + return 0; + return 1; + } +} + +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; +} + + + +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() +{ + if (rep->len > 0) memset(rep->s, 0, rep->sz * sizeof(short)); + rep->len = rep->virt = 0; +} + +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::prev(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 prev((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); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, f, t, star); + stream << ends; + return fmtbase; +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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); +} + +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; +} + +#else + +BitSet shorttoBitSet(unsigned short w) +{ + BitSet r; + r.rep = BitSetalloc(0, &w, 1, 0, 2); trim(r.rep); + return r; +} + +BitSet longtoBitSet(unsigned long w) +{ + BitSet 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); + return r; +} + +BitSet atoBitSet(const char* s, char f, char t, char star) +{ + BitSet 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 r; +} + +#endif + +ostream& operator << (ostream& s, const BitSet& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + +void BitSet::printon(ostream& os, char f, char t, char star) const +// FIXME: Does not respect s.width()! +{ + trim(rep); + register streambuf* sb = os.rdbuf(); + const unsigned short* s = rep->s; + const unsigned short* top = &(s[rep->len - 1]); + + while (s < top) + { + unsigned short a = *s++; + for (int j = 0; j < BITSETBITS; ++j) + { + sb->sputc((a & 1)? t : f); + a >>= 1; + } + } + + if (!rep->virt) + { + unsigned short a = *s; + if (rep->len != 0) + { + for (int j = 0; j < BITSETBITS && a != 0; ++j) + { + sb->sputc((a & 1)? t : f); + a >>= 1; + } + } + sb->sputc(f); + } + else + { + unsigned short a = *s; + unsigned short mask = ONES; + unsigned short himask = (1 << (BITSETBITS - 1)) - 1; + if (rep->len != 0) + { + for (int j = 0; j < BITSETBITS && a != mask; ++j) + { + sb->sputc((a & 1)? t : f); + a = (a >> 1) & himask; + mask = (mask >> 1) & himask; + } + } + sb->sputc(t); + } + + sb->sputc(star); +} + +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; +} + diff --git a/gnu/lib/libg++/g++-include/BitSet.h b/gnu/lib/libg++/g++-include/BitSet.h new file mode 100644 index 00000000000..23ce75a1d14 --- /dev/null +++ b/gnu/lib/libg++/g++-include/BitSet.h @@ -0,0 +1,363 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: BitSet.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _BitSet_h +#ifdef __GNUG__ +#pragma interface +#endif + +#define _BitSet_h 1 + +#include <iostream.h> +#include <limits.h> + +#define BITSETBITS (sizeof(short) * CHAR_BIT) + +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); +}; + +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 prev(int pos, int b = 1) const; + int previous(int pos, int b = 1) const /* Obsolete synonym */ + { return prev(pos, b); } + +// 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='*'); + // BitSettoa is deprecated; do not use in new programs. + 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); + void printon(ostream& s, + char f='0', char t='1', char star='*') const; + +// 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 + + void error(const char* msg) const; + int OK() const; +}; + + +typedef BitSet BitSetTmp; + + + 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); + +// These are inlined regardless of optimization + +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); +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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); +} + +#else /* NO_NRV */ + +inline BitSet operator & (const BitSet& x, const BitSet& y) +{ + BitSet r; and(x, y, r); return r; +} + +inline BitSet operator | (const BitSet& x, const BitSet& y) +{ + BitSet r; or(x, y, r); return r; +} + +inline BitSet operator ^ (const BitSet& x, const BitSet& y) +{ + BitSet r; xor(x, y, r); return r; +} + +inline BitSet operator - (const BitSet& x, const BitSet& y) +{ + BitSet r; diff(x, y, r); return r; +} + +inline BitSet operator ~ (const BitSet& x) +{ + BitSet r; ::complement(x, r); return r; +} + +#endif + +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::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 BitSetBit BitSet::operator [] (int i) +{ + if (i < 0) error("illegal bit index"); + return BitSetBit(this, i); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/BitString.cc b/gnu/lib/libg++/g++-include/BitString.cc new file mode 100644 index 00000000000..261426c3c9d --- /dev/null +++ b/gnu/lib/libg++/g++-include/BitString.cc @@ -0,0 +1,2080 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + BitString class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <BitString.h> +#include <std.h> +#include <limits.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include <strstream.h> + +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 << (sizeof(short)*CHAR_BIT - 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) memmove((void*)ds, (const void*)ss, 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) memset((void*)ds, 0, 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]; + memset(rep, 0, 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); + memcpy(rep->s, old->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; + + memcpy(rep->s, src->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 && + memcmp((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 ((unsigned)(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 ((unsigned)(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 ((unsigned)(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 ((unsigned)(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 ((unsigned)(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 ((unsigned)(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 ((unsigned)(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 || (unsigned)(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 ((unsigned)(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 ((unsigned)(++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::prev(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 ((unsigned)(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; + + unsigned 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); +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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; + + unsigned int startx, starty; + if (startpos < 0) + { + startx = xl + startpos; + starty = yl + startpos; + } + else + startx = starty = startpos; + + if (startx >= xl || starty >= yl) + return; + + const unsigned short* xs = &(x.rep->s[BitStr_index(startx)]); + unsigned short a = *xs++; + unsigned int xp = startx; + + const unsigned short* ys = &(y.rep->s[BitStr_index(starty)]); + unsigned short b = *ys++; + unsigned 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; + + unsigned int startx, starty; + if (startpos < 0) + { + startx = xl + startpos; + starty = yl + startpos; + } + else + startx = starty = startpos; + + if (startx >= xl || 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; +} + +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; +} + +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; +} + +#else /* NO_NRV */ + +BitString common_prefix(const BitString& x, const BitString& y, int startpos) +{ + BitString 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 r; + + 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); + return r; +} + + +BitString common_suffix(const BitString& x, const BitString& y, int startpos) +{ + BitString 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 r; + + 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); + return r; +} + +BitString reverse(const BitString& x) +{ + BitString 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; + return r; +} + +BitString atoBitString(const char* s, char f, char t) +{ + BitString 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; + return res; +} + +BitPattern atoBitPattern(const char* s, char f,char t,char x) +{ + BitPattern 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; +} + +#endif + +extern AllocRing _libgxx_fmtq; + +void BitString::printon(ostream& os, char f, char t) const +{ + unsigned int xl = rep->len; + const unsigned short* ptr = rep->s; + register streambuf *sb = os.rdbuf(); + unsigned short a = 0; + + for (unsigned int i = 0; i < xl; ++i) + { + if (i % BITSTRBITS == 0) + a = *ptr++; + sb->sputc((a & 1)? t : f); + a >>= 1; + } +} +const char* BitStringtoa(const BitString& x, char f, char t) +{ + int wrksiz = x.length() + 2; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, f, t); + stream << ends; + return fmtbase; +} + +ostream& operator << (ostream& s, const BitString& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + +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); + ostrstream stream(fmtbase, wrksiz); + + p.printon(stream, f, t, x); + stream << ends; + return fmtbase; +} + +void BitPattern::printon(ostream& s, char f,char t,char x) const +{ + unsigned int pl = pattern.rep->len; + unsigned int ml = mask.rep->len; + unsigned int l = (pl <= ml)? pl : ml; + register streambuf *sb = s.rdbuf(); + + const unsigned short* ps = pattern.rep->s; + const unsigned short* ms = 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) + sb->sputc((a & 1)? t : f); + else + sb->sputc(x); + a >>= 1; + m >>= 1; + } +} + +ostream& operator << (ostream& s, const BitPattern& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + + +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 + 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; +} + diff --git a/gnu/lib/libg++/g++-include/BitString.h b/gnu/lib/libg++/g++-include/BitString.h new file mode 100644 index 00000000000..cc08b9f92b0 --- /dev/null +++ b/gnu/lib/libg++/g++-include/BitString.h @@ -0,0 +1,759 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: BitString.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _BitString_h +#ifdef __GNUG__ +#pragma interface +#endif + +#define _BitString_h 1 + +#include <stream.h> +#include <limits.h> + +#define BITSTRBITS (sizeof(short) * CHAR_BIT) + +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); +}; + +class BitSubString +{ + friend class BitString; + friend class BitPattern; + +protected: + + BitString& S; + unsigned int pos; + unsigned 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 prev(int pos, unsigned int b = 1) const; + int previous(int pos, unsigned int b = 1) const + { return prev(pos, b); } /* Obsolete synonym */ + +// 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'); + // BitStringtoa is deprecated; do not use in new programs! + friend const char* BitStringtoa(const BitString&, char f='0', char t='1'); + void printon(ostream&, char f='0', char t='1') const; + + friend BitString shorttoBitString(unsigned short); + friend BitString longtoBitString(unsigned long); + + friend ostream& operator << (ostream& s, const BitString&); + +// misc + + void error(const char* msg) const; + +// indirect friends + + friend BitPattern atoBitPattern(const char* s, + char f='0',char t='1',char x='X'); + friend const char* BitPatterntoa(const BitPattern& p, + 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& p, + char f/*='0'*/,char t/*='1'*/,char x/*='X'*/); + void printon(ostream&, char f='0',char t='1',char x='X') const; + 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; +}; + +BitString operator & (const BitString& x, const BitString& y); +BitString operator | (const BitString& x, const BitString& y); +BitString operator ^ (const BitString& x, const BitString& y); +BitString operator << (const BitString& x, int y); +BitString operator >> (const BitString& x, int y); +BitString operator - (const BitString& x, const BitString& y); +BitString operator + (const BitString& x, const BitString& y); +BitString operator + (const BitString& x, unsigned int y); +BitString operator ~ (const BitString& x); +int operator != (const BitString& x, const BitString& y); +int operator>(const BitString& x, const BitString& y); +int operator>=(const BitString& x, const BitString& y); + +extern BitStrRep _nilBitStrRep; +extern BitString _nil_BitString; + +// primitive bit extraction + +// These must be inlined regardless of optimization. + +inline int BitStr_index(int l) { return (unsigned)(l) / BITSTRBITS; } + +inline int BitStr_pos(int l) { return l & (BITSTRBITS - 1); } + + +// 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; +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +inline BitString shorttoBitString(unsigned short w) return r +{ + r.rep = BStr_alloc(0, &w, 0, BITSTRBITS, BITSTRBITS); +} + +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); +} + +#else + +inline BitString shorttoBitString(unsigned short w) +{ + BitString r; r.rep = BStr_alloc(0, &w, 0, BITSTRBITS, BITSTRBITS); return r; +} + +inline BitString longtoBitString(unsigned long w) +{ + BitString 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); + return r; +} + +#endif + +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() {} + + +// 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 void BitString::operator &= (const BitString& y) +{ + and(*this, y, *this); +} + + +inline void BitString::operator |= (const BitString& y) +{ + or(*this, y, *this); +} + +inline void BitString::operator ^= (const BitString& y) +{ + xor(*this, y, *this); +} + +inline void BitString::operator <<= (int y) +{ + lshift(*this, y, *this); +} + +inline void BitString::operator >>= (int y) +{ + rshift(*this, y, *this); +} + +inline void BitString::operator -= (const BitString& y) +{ + diff(*this, y, *this); +} + +inline void BitString::operator += (const BitString& y) +{ + cat(*this, y, *this); +} + +inline void BitString::operator += (unsigned int y) +{ + cat(*this, y, *this); +} + +inline void BitString::complement() +{ + ::complement(*this, *this); +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +inline BitString operator & (const BitString& x, const BitString& y) return r +{ + and(x, y, r); +} + +inline BitString operator | (const BitString& x, const BitString& y) return r +{ + or(x, y, r); +} + +inline BitString operator ^ (const BitString& x, const BitString& y) return r +{ + xor(x, y, r); +} + +inline BitString operator << (const BitString& x, int y) return r +{ + lshift(x, y, r); +} + +inline BitString operator >> (const BitString& x, int y) return r +{ + rshift(x, y, r); +} + +inline BitString operator - (const BitString& x, const BitString& y) return r +{ + diff(x, y, r); +} + +inline BitString operator + (const BitString& x, const BitString& y) return r +{ + cat(x, y, r); +} + +inline BitString operator + (const BitString& x, unsigned int y) return r +{ + cat(x, y, r); +} + +inline BitString operator ~ (const BitString& x) return r +{ + complement(x, r); +} + +#else /* NO_NRV */ + +inline BitString operator & (const BitString& x, const BitString& y) +{ + BitString r; and(x, y, r); return r; +} + +inline BitString operator | (const BitString& x, const BitString& y) +{ + BitString r; or(x, y, r); return r; +} + +inline BitString operator ^ (const BitString& x, const BitString& y) +{ + BitString r; xor(x, y, r); return r; +} + +inline BitString operator << (const BitString& x, int y) +{ + BitString r; lshift(x, y, r); return r; +} + +inline BitString operator >> (const BitString& x, int y) +{ + BitString r; rshift(x, y, r); return r; +} + +inline BitString operator - (const BitString& x, const BitString& y) +{ + BitString r; diff(x, y, r); return r; +} + +inline BitString operator + (const BitString& x, const BitString& y) +{ + BitString r; cat(x, y, r); return r; +} + +inline BitString operator + (const BitString& x, unsigned int y) +{ + BitString r; cat(x, y, r); return r; +} + +inline BitString operator ~ (const BitString& x) +{ + BitString r; complement(x, r); return r; +} + +#endif + +// 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 prev(rep->len, b); +} + +inline int BitString::index(unsigned int bit, int startpos) const +{ + if (startpos >= 0) + return next(startpos - 1, bit); + else + return prev(rep->len + startpos + 1, bit); +} + +inline void BitString::right_trim(unsigned int b) +{ + int nb = (b == 0)? 1 : 0; + rep = BStr_resize(rep, prev(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 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 diff --git a/gnu/lib/libg++/g++-include/Complex.cc b/gnu/lib/libg++/g++-include/Complex.cc new file mode 100644 index 00000000000..c1fb0fda71b --- /dev/null +++ b/gnu/lib/libg++/g++-include/Complex.cc @@ -0,0 +1,262 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Complex.h> +#include <std.h> +#include <builtin.h> + +// 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); +} + +/* from romine@xagsun.epm.ornl.gov */ +Complex /* const */ operator / (const Complex& x, const Complex& y) +{ + double den = fabs(y.real()) + fabs(y.imag()); + if (den == 0.0) x.error ("Attempted division by zero."); + double xrden = x.real() / den; + double xiden = x.imag() / den; + double yrden = y.real() / den; + double yiden = y.imag() / den; + double nrm = yrden * yrden + yiden * yiden; + return Complex((xrden * yrden + xiden * yiden) / nrm, + (xiden * yrden - xrden * yiden) / nrm); +} + +Complex& Complex::operator /= (const Complex& y) +{ + double den = fabs(y.real()) + fabs(y.imag()); + if (den == 0.0) error ("Attempted division by zero."); + double xrden = re / den; + double xiden = im / den; + double yrden = y.real() / den; + double yiden = y.imag() / den; + double nrm = yrden * yrden + yiden * yiden; + re = (xrden * yrden + xiden * yiden) / nrm; + im = (xiden * yrden - xrden * yiden) / nrm; + return *this; +} + +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 /= (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())); +} + +// Corrections based on reports from: thc@cs.brown.edu & saito@sdr.slb.com +Complex /* const */ pow(const Complex& x, const Complex& p) +{ + double h = hypot(x.real(), x.imag()); + if (h <= 0.0) x.error("attempted power of zero magnitude number."); + + double a = atan2(x.imag(), x.real()); + double lr = pow(h, p.real()); + double li = p.real() * a; + if (p.imag() != 0.0) + { + lr /= exp(p.imag() * a); + li += p.imag() * log(h); + } + return Complex(lr * cos(li), lr * sin(li)); +} + +Complex /* const */ pow(const Complex& x, double p) +{ + double h = hypot(x.real(), x.imag()); + if (h <= 0.0) x.error("attempted power of zero magnitude number."); + double lr = pow(h, p); + double a = atan2(x.imag(), x.real()); + double li = p * a; + 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((fabs(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, int 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) +{ +#ifdef _OLD_STREAMS + if (!s.good()) + { + return s; + } +#else + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } +#endif + 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.clear(ios::failbit); + } + else + { + s.putback(ch); + s >> r; + i = 0; + } + x = Complex(r, i); + return s; +} + +Complex 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()); +} + diff --git a/gnu/lib/libg++/g++-include/Complex.h b/gnu/lib/libg++/g++-include/Complex.h new file mode 100644 index 00000000000..fa28a929d47 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Complex.h @@ -0,0 +1,272 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Complex.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _Complex_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Complex_h 1 + + +#include <iostream.h> +#include <math.h> + +class Complex +{ +#ifdef __ATT_complex__ +public: +#else +protected: +#endif + + double re; + double im; + +public: + + double real() const; + double imag() const; + + Complex(); + Complex(const Complex& y); + Complex(double r, double i=0); + + ~Complex(); + + Complex& operator = (const Complex& y); + + Complex& operator += (const Complex& y); + Complex& operator += (double y); + Complex& operator -= (const Complex& y); + Complex& operator -= (double y); + Complex& operator *= (const Complex& y); + Complex& operator *= (double y); + + Complex& operator /= (const Complex& y); + Complex& operator /= (double y); + + void error(const char* msg) const; +}; + + +// non-inline functions + +Complex operator / (const Complex& x, const Complex& y); +Complex operator / (const Complex& x, double y); +Complex operator / (double x, const Complex& y); + +Complex cos(const Complex& x); +Complex sin(const Complex& x); + +Complex cosh(const Complex& x); +Complex sinh(const Complex& x); + +Complex exp(const Complex& x); +Complex log(const Complex& x); + +Complex pow(const Complex& x, int p); +Complex pow(const Complex& x, const Complex& p); +Complex pow(const Complex& x, double y); +Complex sqrt(const Complex& x); + +istream& operator >> (istream& s, Complex& x); +ostream& operator << (ostream& s, const Complex& x); + +// other functions defined as inlines + +int operator == (const Complex& x, const Complex& y); +int operator == (const Complex& x, double y); +int operator != (const Complex& x, const Complex& y); +int operator != (const Complex& x, double y); + +Complex operator - (const Complex& x); +Complex conj(const Complex& x); +Complex operator + (const Complex& x, const Complex& y); +Complex operator + (const Complex& x, double y); +Complex operator + (double x, const Complex& y); +Complex operator - (const Complex& x, const Complex& y); +Complex operator - (const Complex& x, double y); +Complex operator - (double x, const Complex& y); +Complex operator * (const Complex& x, const Complex& y); +Complex operator * (const Complex& x, double y); +Complex operator * (double x, const Complex& y); + +double real(const Complex& x); +double imag(const Complex& x); +double abs(const Complex& x); +double norm(const Complex& x); +double arg(const Complex& x); + +Complex polar(double r, double t = 0.0); + + +// inline members + +inline double Complex::real() const { return re; } +inline double 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; +} + + +// functions + +inline int operator == (const Complex& x, const Complex& y) +{ + return x.real() == y.real() && x.imag() == y.imag(); +} + +inline int operator == (const Complex& x, double y) +{ + return x.imag() == 0.0 && x.real() == y; +} + +inline int operator != (const Complex& x, const Complex& y) +{ + return x.real() != y.real() || x.imag() != y.imag(); +} + +inline int operator != (const Complex& x, double y) +{ + return x.imag() != 0.0 || x.real() != y; +} + +inline Complex operator - (const Complex& x) +{ + return Complex(-x.real(), -x.imag()); +} + +inline Complex conj(const Complex& x) +{ + return Complex(x.real(), -x.imag()); +} + +inline Complex operator + (const Complex& x, const Complex& y) +{ + return Complex(x.real() + y.real(), x.imag() + y.imag()); +} + +inline Complex operator + (const Complex& x, double y) +{ + return Complex(x.real() + y, x.imag()); +} + +inline Complex operator + (double x, const Complex& y) +{ + return Complex(x + y.real(), y.imag()); +} + +inline Complex operator - (const Complex& x, const Complex& y) +{ + return Complex(x.real() - y.real(), x.imag() - y.imag()); +} + +inline Complex operator - (const Complex& x, double y) +{ + return Complex(x.real() - y, x.imag()); +} + +inline Complex operator - (double x, const Complex& y) +{ + return Complex(x - y.real(), -y.imag()); +} + +inline Complex operator * (const Complex& x, double y) +{ + return Complex(x.real() * y, x.imag() * y); +} + +inline Complex operator * (double x, const Complex& y) +{ + return Complex(x * y.real(), x * y.imag()); +} + +inline double real(const Complex& x) +{ + return x.real(); +} + +inline double imag(const Complex& x) +{ + return x.imag(); +} + +inline double abs(const Complex& x) +{ + return hypot(x.real(), x.imag()); +} + +inline double norm(const Complex& x) +{ + return (x.real() * x.real() + x.imag() * x.imag()); +} + +inline double arg(const Complex& x) +{ + return atan2(x.imag(), x.real()); +} + +inline Complex polar(double r, double t) +{ + return Complex(r * cos(t), r * sin(t)); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/CursesW.cc b/gnu/lib/libg++/g++-include/CursesW.cc new file mode 100644 index 00000000000..9533f691556 --- /dev/null +++ b/gnu/lib/libg++/g++-include/CursesW.cc @@ -0,0 +1,255 @@ +/* +Copyright (C) 1989, 1992 Free Software Foundation + written by Eric Newton (newton@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stdio.h> +#include <stdarg.h> +#include <builtin.h> +#include <values.h> +#ifndef _OLD_STREAMS +#include <strstream.h> +//#include <ioprivate.h> +#endif +// Include CurseW.h and/or curses.h *after* iostream includes, +// because curses.h defines a clear macro that conflicts with iostream. Sigh. +#include <CursesW.h> + +#if _G_HAVE_CURSES + +int CursesWindow::count = 0; + +/* + * C++ interface to curses library. + * + */ + +#if !defined(_IO_MAGIC) && !defined(HAVE_VSCANF) &&!defined vsscanf +extern "C" int _doscan(FILE *, const char*, va_list args); + +static int vsscanf(char *buf, const char * fmt, va_list args) +{ + FILE b; +#ifdef _IOSTRG + b._flag = _IOREAD|_IOSTRG; +#else + b._flag = _IOREAD; +#endif + b._base = (unsigned char*)buf; + b._ptr = (unsigned char*)buf; + b._cnt = BUFSIZ; + return _doscan(&b, fmt, args); +} +#endif + +/* + * 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); +#ifdef VMS + int result = wscanw(w , fmt , args); +#else /* NOT VMS */ + char buf[BUFSIZ]; + int result = wgetstr(w, buf); + if (result == OK) { + +#ifdef _IO_MAGIC /* GNU iostreams */ + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, args); +#else + result = vsscanf(buf, fmt, args); +#endif + } +#endif /* !VMS */ + 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]; + int result = wmove(w, y, x); + if (result == OK) +#ifdef VMS + result=wscanw(w , fmt , args); +#else /* !VMS */ + { + result = wgetstr(w, buf); + if (result == OK) { +#ifdef _IO_MAGIC /* GNU iostreams */ + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, args); +#else + result = vsscanf(buf, fmt, args); +#endif + } + } +#endif /* !VMS */ + va_end(args); + return result; +} + +int CursesWindow::printw(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + va_end(args); + return waddstr(w, buf); +} + + +int CursesWindow::mvprintw(int y, int x, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + int result = wmove(w, y, x); + if (result == OK) + { + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + 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"); + } +} + +#endif /* _G_HAVE_CURSES */ diff --git a/gnu/lib/libg++/g++-include/CursesW.h b/gnu/lib/libg++/g++-include/CursesW.h new file mode 100644 index 00000000000..ec378a3a424 --- /dev/null +++ b/gnu/lib/libg++/g++-include/CursesW.h @@ -0,0 +1,581 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: CursesW.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _CursesWindow_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _CursesWindow_h + +#include <_G_config.h> +#if _G_HAVE_CURSES +#include <curses.h> + +/* SCO 3.2v4 curses.h includes term.h, which defines lines as a macro. + Undefine it here, because CursesWindow uses lines as a method. */ +#undef lines + +// "Convert" macros to inlines, if needed. +#ifdef addch +inline int (addch)(char ch) { return addch(ch); } +#undef addch +#endif +#ifdef addstr +/* The (char*) cast is to hack around missing const's */ +inline int (addstr)(const char * str) { return addstr((char*)str); } +#undef addstr +#endif +#ifdef clear +inline int (clear)() { return clear(); } +#undef clear +#endif +#ifdef clearok +inline int (clearok)(WINDOW* win, int bf) { return clearok(win, bf); } +#undef clearok +#else +extern "C" int clearok(WINDOW*, int); +#endif +#ifdef clrtobot +inline int (clrtobot)() { return clrtobot(); } +#undef clrtobot +#endif +#ifdef clrtoeol +inline int (clrtoeol)() { return clrtoeol(); } +#undef clrtoeol +#endif +#ifdef delch +inline int (delch)() { return delch(); } +#undef delch +#endif +#ifdef deleteln +inline int (deleteln)() { return deleteln(); } +#undef deleteln +#endif +#ifdef erase +inline int (erase)() { return erase(); } +#undef erase +#endif +#ifdef flushok +inline int (flushok)(WINDOW* _win, int _bf) { return flushok(_win, _bf); } +#undef flushok +#else +#define _no_flushok +#endif +#ifdef getch +inline int (getch)() { return getch(); } +#undef getch +#endif +#ifdef getstr +inline int (getstr)(char *_str) { return getstr(_str); } +#undef getstr +#endif +#ifdef getyx +inline void (getyx)(WINDOW* win, int& y, int& x) { getyx(win, y, x); } +#undef getyx +#endif +#ifdef inch +inline int (inch)() { return inch(); } +#undef inch +#endif +#ifdef insch +inline int (insch)(char c) { return insch(c); } +#undef insch +#endif +#ifdef insertln +inline int (insertln)() { return insertln(); } +#undef insertln +#endif +#ifdef leaveok +inline int (leaveok)(WINDOW* win, int bf) { return leaveok(win, bf); } +#undef leaveok +#else +extern "C" int leaveok(WINDOW* win, int bf); +#endif +#ifdef move +inline int (move)(int x, int y) { return move(x, y); } +#undef move +#endif +#ifdef refresh +inline int (rfresh)() { return refresh(); } +#undef refresh +#endif +#ifdef scrollok +inline int (scrollok)(WINDOW* win, int bf) { return scrollok(win, bf); } +#undef scrollok +#else +#ifndef hpux +extern "C" int scrollok(WINDOW*, int); +#else +extern "C" int scrollok(WINDOW*, char); +#endif +#endif +#ifdef standend +inline int (standend)() { return standend(); } +#undef standend +#endif +#ifdef standout +inline int (standout)() { return standout(); } +#undef standout +#endif +#ifdef wstandend +inline int (wstandend)(WINDOW *win) { return wstandend(win); } +#undef wstandend +#endif +#ifdef wstandout +inline int (wstandout)(WINDOW *win) { return wstandout(win); } +#undef wstandout +#endif +#ifdef wattrset +inline int (wattrset)(WINDOW *win, int att) { return wattrset(win, att); } +#undef wattrset +#endif +#ifdef winch +inline int (winch)(WINDOW* win) { return winch(win); } +#undef winch +#endif + +#ifdef mvwaddch +inline int (mvwaddch)(WINDOW *win, int y, int x, char ch) +{ return mvwaddch(win, y, x, ch); } +#undef mvwaddch +#endif +#ifdef mvwaddstr +inline int (mvwaddstr)(WINDOW *win, int y, int x, const char * str) +{ return mvwaddstr(win, y, x, (char*)str); } +#undef mvwaddstr +#endif +#ifdef mvwdelch +inline int (mvwdelch)(WINDOW *win, int y, int x) { return mvwdelch(win, y, x);} +#undef mvwdelch +#endif +#ifdef mvwgetch +inline int (mvwgetch)(WINDOW *win, int y, int x) { return mvwgetch(win, y, x);} +#undef mvwgetch +#endif +#ifdef mvwgetstr +inline int (mvwgetstr)(WINDOW *win, int y, int x, char *str) +{return mvwgetstr(win,y,x, str);} +#undef mvwgetstr +#endif +#ifdef mvwinch +inline int (mvwinch)(WINDOW *win, int y, int x) { return mvwinch(win, y, x);} +#undef mvwinch +#endif +#ifdef mvwinsch +inline int (mvwinsch)(WINDOW *win, int y, int x, char c) +{ return mvwinsch(win, y, x, c); } +#undef mvwinsch +#endif + +#ifdef mvaddch +inline int (mvaddch)(int y, int x, char ch) +{ return mvaddch(y, x, ch); } +#undef mvaddch +#endif +#ifdef mvaddstr +inline int (mvaddstr)(int y, int x, const char * str) +{ return mvaddstr(y, x, (char*)str); } +#undef mvaddstr +#endif +#ifdef mvdelch +inline int (mvdelch)(int y, int x) { return mvdelch(y, x);} +#undef mvdelch +#endif +#ifdef mvgetch +inline int (mvgetch)(int y, int x) { return mvgetch(y, x);} +#undef mvgetch +#endif +#ifdef mvgetstr +inline int (mvgetstr)(int y, int x, char *str) {return mvgetstr(y, x, str);} +#undef mvgetstr +#endif +#ifdef mvinch +inline int (mvinch)(int y, int x) { return mvinch(y, x);} +#undef mvinch +#endif +#ifdef mvinsch +inline int (mvinsch)(int y, int x, char c) +{ return mvinsch(y, x, c); } +#undef mvinsch +#endif + +/* + * + * 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, const 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(int bf); + int clrtobot(); + int clrtoeol(); + int delch(); + int mvdelch(int y, int x); + int deleteln(); + +// screen control + int scroll(); + int scrollok(int bf); + int touchwin(); + int refresh(); + int leaveok(int bf); +#ifndef _no_flushok + int flushok(int bf); +#endif + int standout(); + int standend(); + +// multiple window control + int overlay(CursesWindow &win); + int overwrite(CursesWindow &win); + + +// 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); +} + + +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) +{ + // The (char*) cast is to hack around prototypes in curses.h that + // have const missing in the parameter lists. [E.g. SVR4] + return ::waddstr(w, (char*)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::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)==ERR) ? ERR : ::waddch(w, ch); +} + +inline int CursesWindow::mvgetch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wgetch(w); +} + +inline int CursesWindow::mvaddstr(int y, int x, const char * str) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::waddstr(w, (char*)str); +} + +inline int CursesWindow::mvgetstr(int y, int x, char * str) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wgetstr(w, str); +} + +inline int CursesWindow::mvinch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::winch(w); +} + +inline int CursesWindow::mvdelch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wdelch(w); +} + +inline int CursesWindow::mvinsch(int y, int x, char ch) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::winsch(w, ch); +} + +inline int CursesWindow::refresh() +{ + return ::wrefresh(w); +} + +inline int CursesWindow::clearok(int bf) +{ + return ::clearok(w,bf); +} + +inline int CursesWindow::leaveok(int bf) +{ + return ::leaveok(w,bf); +} + +inline int CursesWindow::scrollok(int bf) +{ + return ::scrollok(w,bf); +} + +#ifndef _no_flushok +inline int CursesWindow::flushok(int bf) +{ + return ::flushok(w, bf); +} +#endif + +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 /* _G_HAVE_CURSES */ +#endif diff --git a/gnu/lib/libg++/g++-include/DLList.cc b/gnu/lib/libg++/g++-include/DLList.cc new file mode 100644 index 00000000000..25c0be4e549 --- /dev/null +++ b/gnu/lib/libg++/g++-include/DLList.cc @@ -0,0 +1,327 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _G_NO_TEMPLATES +#ifdef __GNUG__ +//#pragma implementation +#endif +#include <values.h> +#include <stream.h> +#include <builtin.h> +#include "DLList.h" + +void BaseDLList::error(const char* msg) +{ + (*lib_error_handler)("DLList", msg); +} + +int BaseDLList::length() +{ + int l = 0; + BaseDLNode* t = h; + if (t != 0) do { ++l; t = t->fd; } while (t != h); + return l; +} + +// Note: This is an internal method. It does *not* free old contents! + +void BaseDLList::copy(const BaseDLList& a) +{ + if (a.h == 0) + h = 0; + else + { + BaseDLNode* p = a.h; + BaseDLNode* t = copy_node(p->item()); + h = t; + p = p->fd; + while (p != a.h) + { + BaseDLNode* n = copy_node(p->item()); + t->fd = n; + n->bk = t; + t = n; + p = p->fd; + } + t->fd = h; + h->bk = t; + return; + } +} + +void BaseDLList::clear() +{ + if (h == 0) + return; + + BaseDLNode* p = h->fd; + h->fd = 0; + h = 0; + + while (p != 0) + { + BaseDLNode* nxt = p->fd; + delete_node(p); + p = nxt; + } +} + +BaseDLList& BaseDLList::operator = (const BaseDLList& a) +{ + if (h != a.h) + { + clear(); + copy(a); + } + return *this; +} + + +Pix BaseDLList::prepend(void *datum) +{ + BaseDLNode* t = copy_node(datum); + 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 BaseDLList::append(void *datum) +{ + BaseDLNode* t = copy_node(datum); + 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 BaseDLList::ins_after(Pix p, void *datum) +{ + if (p == 0) return prepend(datum); + BaseDLNode* u = (BaseDLNode*) p; + BaseDLNode* t = copy_node(datum); + t->bk = u; + t->fd = u->fd; + u->fd->bk = t; + u->fd = t; + return Pix(t); +} + +Pix BaseDLList::ins_before(Pix p, void *datum) +{ + if (p == 0) error("null Pix"); + BaseDLNode* u = (BaseDLNode*) p; + BaseDLNode* t = copy_node(datum); + t->bk = u->bk; + t->fd = u; + u->bk->fd = t; + u->bk = t; + if (u == h) h = t; + return Pix(t); +} + +void BaseDLList::join(BaseDLList& b) +{ + BaseDLNode* t = b.h; + b.h = 0; + if (h == 0) + h = t; + else if (t != 0) + { + BaseDLNode* l = t->bk; + h->bk->fd = t; + t->bk = h->bk; + h->bk = l; + l->fd = h; + } +} + +int BaseDLList::owns(Pix p) +{ + BaseDLNode* t = h; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->fd; + } while (t != h); + } + return 0; +} + +void BaseDLList::del(Pix& p, int dir) +{ + if (p == 0) error("null Pix"); + BaseDLNode* t = (BaseDLNode*) 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; +} + +void BaseDLList::del_after(Pix& p) +{ + if (p == 0) + { + del_front(); + return; + } + + BaseDLNode* b = (BaseDLNode*) p; + BaseDLNode* t = b->fd; + + if (b == t) + { + h = 0; + p = 0; + } + else + { + t->bk->fd = t->fd; + t->fd->bk = t->bk; + if (t == h) h = t->fd; + } + delete_node(t); +} + +void BaseDLList::remove_front(void *dst) +{ + if (h == 0) + error("remove_front of empty list"); + else { + BaseDLNode* t = h; + copy_item(dst, t->item()); + if (h->fd == h) + h = 0; + else + { + h->fd->bk = h->bk; + h->bk->fd = h->fd; + h = h->fd; + } + delete_node(t); + } +} + +void BaseDLList::del_front() +{ + if (h == 0) + error("del_front of empty list"); + BaseDLNode* t = h; + if (h->fd == h) + h = 0; + else + { + h->fd->bk = h->bk; + h->bk->fd = h->fd; + h = h->fd; + } + delete_node(t); +} + +void BaseDLList::remove_rear(void *dst) +{ + if (h == 0) + error("remove_rear of empty list"); + else + { + BaseDLNode* t = h->bk; + copy_item(dst, t->item()); + if (h->fd == h) + h = 0; + else + { + t->fd->bk = t->bk; + t->bk->fd = t->fd; + } + delete_node(t); + } +} + +void BaseDLList::del_rear() +{ + if (h == 0) + error("del_rear of empty list"); + BaseDLNode* t = h->bk; + if (h->fd == h) + h = 0; + else + { + t->fd->bk = t->bk; + t->bk->fd = t->fd; + } + delete_node(t); +} + + +int BaseDLList::OK() +{ + int v = 1; + if (h != 0) + { + BaseDLNode* 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; +} +#endif diff --git a/gnu/lib/libg++/g++-include/DLList.h b/gnu/lib/libg++/g++-include/DLList.h new file mode 100644 index 00000000000..80fe64359d1 --- /dev/null +++ b/gnu/lib/libg++/g++-include/DLList.h @@ -0,0 +1,125 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: DLList.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _DLList_h +#ifdef __GNUG__ +//#pragma interface +#endif +#define _DLList_h 1 + +#include <Pix.h> + +struct BaseDLNode { + BaseDLNode *bk; + BaseDLNode *fd; + void *item() {return (void*)(this+1);} //Return ((DLNode<T>*)this)->hd +}; + +template<class T> +class DLNode : public BaseDLNode +{ + public: + T hd; + DLNode() { } + DLNode(const T& h, DLNode* p = 0, DLNode* n = 0) + : hd(h) { bk = p; fd = n; } + ~DLNode() { } +}; + +class BaseDLList { + protected: + BaseDLNode *h; + + BaseDLList() { h = 0; } + void copy(const BaseDLList&); + BaseDLList& operator= (const BaseDLList& a); + virtual void delete_node(BaseDLNode*node) = 0; + virtual BaseDLNode* copy_node(void* datum) = 0; + virtual void copy_item(void *dst, void *src) = 0; + virtual ~BaseDLList() { } + + Pix prepend(void*); + Pix append(void*); + Pix ins_after(Pix p, void *datum); + Pix ins_before(Pix p, void *datum); + void remove_front(void *dst); + void remove_rear(void *dst); + void join(BaseDLList&); + + public: + int empty() { return h == 0; } + int length(); + void clear(); + void error(const char* msg); + int owns(Pix p); + int OK(); + void del(Pix& p, int dir = 1); + void del_after(Pix& p); + void del_front(); + void del_rear(); +}; + +template <class T> +class DLList : public BaseDLList { + //friend class <T>DLListTrav; + + virtual void delete_node(BaseDLNode *node) { delete (DLNode<T>*)node; } + virtual BaseDLNode* copy_node(void *datum) + { return new DLNode<T>(*(T*)datum); } + virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; } + + public: + DLList() : BaseDLList() { } + DLList(const DLList<T>& a) : BaseDLList() { copy(a); } + + DLList<T>& operator = (const DLList<T>& a) + { BaseDLList::operator=((const BaseDLList&) a); return *this; } + virtual ~DLList() { clear(); } + + Pix prepend(T& item) {return BaseDLList::prepend(&item);} + Pix append(T& item) {return BaseDLList::append(&item);} + + void join(DLList<T>& a) { BaseDLList::join(a); } + + T& front() { + if (h == 0) error("front: empty list"); + return ((DLNode<T>*)h)->hd; } + T& rear() { + if (h == 0) error("rear: empty list"); + return ((DLNode<T>*)h->bk)->hd; + } + T remove_front() { T dst; BaseDLList::remove_front(&dst); return dst; } + T remove_rear() { T dst; BaseDLList::remove_rear(&dst); return dst; } + + T& operator () (Pix p) { + if (p == 0) error("null Pix"); + return ((DLNode<T>*)p)->hd; + } + Pix first() { return Pix(h); } + Pix last() { return (h == 0)? 0 : Pix(h->bk); } + void next(Pix& p) + { p = (p == 0 || p == h->bk)? 0 : Pix(((DLNode<T>*)p)->fd); } + void prev(Pix& p) + { p = (p == 0 || p == h)? 0 : Pix(((DLNode<T>*)p)->bk); } + Pix ins_after(Pix p, T& item) {return BaseDLList::ins_after(p, &item); } + Pix ins_before(Pix p, T& item) {return BaseDLList::ins_before(p, &item);} +}; + +#endif diff --git a/gnu/lib/libg++/g++-include/DiscUnif.cc b/gnu/lib/libg++/g++-include/DiscUnif.cc new file mode 100644 index 00000000000..136ad11aba2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/DiscUnif.cc @@ -0,0 +1,29 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <DiscUnif.h> + +double DiscreteUniform::operator()() +{ + long tmp = long(floor(delta * pGenerator -> asDouble())); + return( double(pLow + tmp) ); +} + diff --git a/gnu/lib/libg++/g++-include/DiscUnif.h b/gnu/lib/libg++/g++-include/DiscUnif.h new file mode 100644 index 00000000000..86991000790 --- /dev/null +++ b/gnu/lib/libg++/g++-include/DiscUnif.h @@ -0,0 +1,75 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: DiscUnif.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _DiscreteUniform_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _DiscreteUniform_h 1 + +#include <Random.h> + +// +// 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()(); +}; + + +inline DiscreteUniform::DiscreteUniform(long low, long high, RNG *gen) +: Random(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 diff --git a/gnu/lib/libg++/g++-include/Erlang.cc b/gnu/lib/libg++/g++-include/Erlang.cc new file mode 100644 index 00000000000..da3e4e7bd06 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Erlang.cc @@ -0,0 +1,32 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Erlang.h> + +double Erlang::operator()() +{ + double prod = 1.0; + + for (int i = 0; i < k; i++) { + prod *= pGenerator -> asDouble(); + } + return(-log(prod)/a); +} diff --git a/gnu/lib/libg++/g++-include/Erlang.h b/gnu/lib/libg++/g++-include/Erlang.h new file mode 100644 index 00000000000..54bcfcb69ab --- /dev/null +++ b/gnu/lib/libg++/g++-include/Erlang.h @@ -0,0 +1,71 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Erlang.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +*/ + +#ifndef _Erlang_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Erlang_h 1 + +#include <Random.h> + +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()(); + +}; + + +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) : Random(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 diff --git a/gnu/lib/libg++/g++-include/Fix.cc b/gnu/lib/libg++/g++-include/Fix.cc new file mode 100644 index 00000000000..0a5bc2d793b --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix.cc @@ -0,0 +1,615 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +// +// Fix.cc : variable length fixed point data type class functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <math.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <strstream.h> +#include <Fix.h> + +// 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 + +static 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]); + memset(z, 0, 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, const _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(const 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 <<= 16; + a += 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(const _Fix x, const _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 < (int)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; + +void Fix::printon(ostream& s, int width) const +{ + char format[20]; + double val = value(*this); + int old_precision = s.precision(width-3); + long old_flags = s.setf(ios::fixed, ios::fixed|ios::scientific); + if (val >= 0) + s << ' '; + s.width(width-2); + s << val; + s.precision(old_precision); + s.flags(old_flags); +} + +char* Ftoa(Fix& x, int width) +{ + int wrksiz = width + 2; + char *fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, width); + stream << ends; + return fmtbase; +} + +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.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } + + char sign = 0, point = 0; + char ch; + s >> ws; + if (!s.good()) + { + s.clear(ios::failbit|s.rdstate()); + 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.putback(ch); + if (!got_one) + s.clear(ios::failbit|s.rdstate()); + 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 = "; +#ifdef _OLD_STREAMS + cout << Itoa(mantissa(x),16,4*x.rep->siz); +#else + int old_flags = cout.setf(ios::hex, ios::hex|ios::dec|ios::oct); + cout.width(4*x.rep->siz); + cout << mantissa(x); + cout.setf(old_flags, ios::hex|ios::dec|ios::oct); +#endif + cout << "\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 < (int)r->siz; i++ ) + r->s[i] = 0xffff; + mask(r); + } +} + +void Fix_overflow_wrap(_Fix&) {} + +void Fix_overflow_warning_saturate(_Fix& r) { + Fix_overflow_warning(r); + Fix_overflow_saturate(r); +} + +void Fix_overflow_warning(_Fix&) { + cerr << "Fix: overflow warning\n"; +} + +void Fix_overflow_error(_Fix&) { + cerr << "Fix: overflow error\n"; + abort(); +} + diff --git a/gnu/lib/libg++/g++-include/Fix.h b/gnu/lib/libg++/g++-include/Fix.h new file mode 100644 index 00000000000..db1b7896183 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix.h @@ -0,0 +1,471 @@ +// +// Fix.h : variable length fixed point data type +// +// $Id: Fix.h,v 1.1 1995/10/18 08:38:15 deraadt Exp $ +// + +#ifndef _Fix_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix_h 1 + +#include <stream.h> +#include <std.h> +#include <stddef.h> +#include <Integer.h> +#include <builtin.h> + +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 _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, const Fix&); + Fix(int, double); + Fix(int, const _Fix); + + ~Fix(); + + Fix operator = (Fix&); + Fix operator = (double); + + friend int operator == (const Fix&, const Fix& ); + friend int operator != (const Fix&, const Fix&); + + friend int operator < (const Fix&, const Fix&); + friend int operator <= (const Fix&, const Fix&); + friend int operator > (const Fix&, const Fix&); + friend int operator >= (const Fix&, const 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&); // min + 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); + void printon(ostream&, int width = Fix_default_print_width) const; + friend Fix atoF(const char*, int len = Fix_default_length); + + friend istream& operator >> (istream&, Fix&); + friend ostream& operator << (ostream&, const 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(const Fix&); // double value + friend int length(const 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(const _Fix, const _Fix = &_Frep_0); + + friend _Fix new_Fix(uint16); + friend _Fix new_Fix(uint16, const _Fix); + friend _Fix new_Fix(uint16, double); + + friend _Fix copy(const _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(const _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, const 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, const _Fix 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 == (const Fix& x, const Fix& y) +{ + return compare(x.rep, y.rep) == 0; +} + +inline int operator != (const Fix& x, const Fix& y) +{ + return compare(x.rep, y.rep) != 0; +} + +inline int operator < (const Fix& x, const Fix& y) +{ + return compare(x.rep, y.rep) < 0; +} + +inline int operator <= (const Fix& x, const Fix& y) +{ + return compare(x.rep, y.rep) <= 0; +} + +inline int operator > (const Fix& x, const Fix& y) +{ + return compare(x.rep, y.rep) > 0; +} + +inline int operator >= (const Fix& x, const 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; +} + +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(const Fix& x) +{ + return x.rep->len; +} + +inline ostream& operator << (ostream& s, const Fix& y) +{ + if (s.opfx()) + y.printon(s); + return s; +} + +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 diff --git a/gnu/lib/libg++/g++-include/Fix16.cc b/gnu/lib/libg++/g++-include/Fix16.cc new file mode 100644 index 00000000000..a66bfbf9b19 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix16.cc @@ -0,0 +1,238 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +// +// Fix.cc : fixed precision class support functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Fix16.h> + +// 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 * (const Fix32& a, const 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 / (const Fix16& a, const 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 / (const Fix32& a, const 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 ((unsigned)(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) const +{ + (*Fix16_overflow_handler)(i); +} + +void Fix32::overflow(long& i) const +{ + (*Fix32_overflow_handler)(i); +} + +void Fix16::range_error(short& i) const +{ + (*Fix16_range_error_handler)(i); +} + +void Fix32::range_error(long& i) const +{ + (*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(); } + diff --git a/gnu/lib/libg++/g++-include/Fix16.h b/gnu/lib/libg++/g++-include/Fix16.h new file mode 100644 index 00000000000..37fb54f409b --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix16.h @@ -0,0 +1,650 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Fix16.h,v 1.1 1995/10/18 08:38:16 deraadt Exp $ +*/ + +#ifndef _Fix16_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix16_h 1 + +#include <stream.h> +#include <std.h> + +// 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 ((long)((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() const; + + +public: + Fix16(); + Fix16(const Fix16& f); + Fix16(double d); + Fix16(const Fix32& f); + + ~Fix16(); + + Fix16& operator=(const Fix16& f); + Fix16& operator=(double d); + Fix16& operator=(const Fix32& f); + + friend short& mantissa(Fix16& f); + friend const short& mantissa(const Fix16& f); + friend double value(const Fix16& f); + + Fix16 operator + () const; + Fix16 operator - () const; + + friend Fix16 operator + (const Fix16& f, const Fix16& g); + friend Fix16 operator - (const Fix16& f, const Fix16& g); + friend Fix32 operator * (const Fix16& f, const Fix16& g); + friend Fix16 operator / (const Fix16& f, const Fix16& g); + friend Fix16 operator << (const Fix16& f, int b); + friend Fix16 operator >> (const Fix16& f, int b); + + Fix16& operator += (const Fix16& f); + Fix16& operator -= (const Fix16& f); + Fix16& operator *= (const Fix16& ); + Fix16& operator /= (const Fix16& f); + + Fix16& operator <<=(int b); + Fix16& operator >>=(int b); + + friend int operator == (const Fix16& f, const Fix16& g); + friend int operator != (const Fix16& f, const Fix16& g); + friend int operator >= (const Fix16& f, const Fix16& g); + friend int operator <= (const Fix16& f, const Fix16& g); + friend int operator > (const Fix16& f, const Fix16& g); + friend int operator < (const Fix16& f, const Fix16& g); + + friend istream& operator >> (istream& s, Fix16& f); + friend ostream& operator << (ostream& s, const Fix16& f); + + void overflow(short&) const; + void range_error(short&) const; + + friend Fix16 operator * (const Fix16& f, int g); + friend Fix16 operator * (int g, const 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() const; + + +public: + Fix32(); + Fix32(const Fix32& f); + Fix32(const Fix16& f); + Fix32(double d); + ~Fix32(); + + Fix32& operator = (const Fix32& f); + Fix32& operator = (const Fix16& f); + Fix32& operator = (double d); + + friend long& mantissa(Fix32& f); + friend const long& mantissa(const Fix32& f); + friend double value(const Fix32& f); + + Fix32 operator + () const; + Fix32 operator - () const; + + friend Fix32 operator + (const Fix32& f, const Fix32& g); + friend Fix32 operator - (const Fix32& f, const Fix32& g); + friend Fix32 operator * (const Fix32& f, const Fix32& g); + friend Fix32 operator / (const Fix32& f, const Fix32& g); + friend Fix32 operator << (const Fix32& f, int b); + friend Fix32 operator >> (const Fix32& f, int b); + + friend Fix32 operator * (const Fix16& f, const Fix16& g); + + Fix32& operator += (const Fix32& f); + Fix32& operator -= (const Fix32& f); + Fix32& operator *= (const Fix32& f); + Fix32& operator /= (const Fix32& f); + Fix32& operator <<=(int b); + Fix32& operator >>=(int b); + + friend int operator == (const Fix32& f, const Fix32& g); + friend int operator != (const Fix32& f, const Fix32& g); + friend int operator >= (const Fix32& f, const Fix32& g); + friend int operator <= (const Fix32& f, const Fix32& g); + friend int operator > (const Fix32& f, const Fix32& g); + friend int operator < (const Fix32& f, const Fix32& g); + + friend istream& operator >> (istream& s, Fix32& f); + friend ostream& operator << (ostream& s, const Fix32& f); + + void overflow(long& i) const; + void range_error(long& i) const; + + friend Fix32 operator * (const Fix32& f, int g); + friend Fix32 operator * (int g, const Fix32& f); + Fix32& operator *= (int 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; + +#if defined(SHORT_NAMES) || defined(VMS) +#define set_overflow_handler sohndl +#define set_range_error_handler srnghdl +#endif + + +// 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&); + + +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() const +{ + return Fix16_div * m; +} + +inline Fix16::Fix16() +{ + m = 0; +} + +inline Fix16::Fix16(const Fix16& f) +{ + m = f.m; +} + +inline Fix16::Fix16(double d) +{ + m = assign(d); +} + + +inline Fix16& Fix16::operator=(const 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() const +{ + return Fix32_div * m; +} + + +inline Fix32::Fix32(const Fix32& f) +{ + m = f.m; +} + +inline Fix32::Fix32(const Fix16& f) +{ + m = long(f.m) << 16; +} + +inline Fix32::Fix32(double d) +{ + m = assign(d); +} + +inline Fix16::Fix16(const Fix32& f) +{ + m = f.m >> 16; +} + + +inline Fix16& Fix16::operator=(const Fix32& f) +{ + m = f.m >> 16; + return *this; +} + +inline Fix32& Fix32::operator=(const Fix32& f) +{ + m = f.m; + return *this; +} + +inline Fix32& Fix32::operator=(const 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 const short& mantissa(const Fix16& f) +{ + return f.m; +} + +inline double value(const Fix16& f) +{ + return double(f); +} + +inline Fix16 Fix16::operator+() const +{ + return m; +} + +inline Fix16 Fix16::operator-() const +{ + return -m; +} + +inline Fix16 operator+(const Fix16& f, const 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-(const Fix16& f, const 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*(const Fix16& f, const Fix16& g) +{ + return Fix32( long( long(f.m) * long(g.m) << 1)); +} + +inline Fix16 operator<<(const Fix16& a, int b) +{ + return a.m << b; +} + +inline Fix16 operator>>(const Fix16& a, int b) +{ + return a.m >> b; +} + +inline Fix16& Fix16:: operator+=(const Fix16& f) +{ + return *this = *this + f; +} + +inline Fix16& Fix16:: operator-=(const Fix16& f) +{ + return *this = *this - f; +} + +inline Fix16& Fix16::operator*=(const Fix16& f) +{ + return *this = *this * f; +} + +inline Fix16& Fix16:: operator/=(const 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==(const Fix16& f, const Fix16& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix16& f, const Fix16& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix16& f, const Fix16& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix16& f, const Fix16& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix16& f, const Fix16& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix16& f, const 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, const Fix16& f) +{ + return s << double(f); +} + + +inline Fix16 operator*(const Fix16& f, int g) +{ + return Fix16(short(f.m * g)); +} + +inline Fix16 operator*(int g, const 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 const long& mantissa(const Fix32& f) +{ + return f.m; +} + +inline double value(const Fix32& f) +{ + return double(f); +} + +inline Fix32 Fix32::operator+() const +{ + return m; +} + +inline Fix32 Fix32::operator-() const +{ + return -m; +} + +inline Fix32 operator+(const Fix32& f, const 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-(const Fix32& f, const 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<<(const Fix32& a, int b) +{ + return a.m << b; +} + +inline Fix32 operator>>(const Fix32& a, int b) +{ + return a.m >> b; +} + +inline Fix32& Fix32::operator+=(const Fix32& f) +{ + return *this = *this + f; +} + +inline Fix32& Fix32::operator-=(const Fix32& f) +{ + return *this = *this - f; +} + +inline Fix32& Fix32::operator*=(const Fix32& f) +{ + return *this = *this * f; +} + +inline Fix32& Fix32::operator/=(const 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==(const Fix32& f, const Fix32& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix32& f, const Fix32& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix32& f, const Fix32& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix32& f, const Fix32& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix32& f, const Fix32& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix32& f, const 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, const Fix32& f) +{ + return s << double(f); +} + +inline Fix32 operator*(const Fix32& f, int g) +{ + return Fix32(long(f.m * g)); +} + +inline Fix32 operator*(int g, const Fix32& f) +{ + return f * g; +} + + + +inline Fix32& Fix32::operator*=(int g) +{ + return *this = *this * g; +} + +#endif diff --git a/gnu/lib/libg++/g++-include/Fix24.cc b/gnu/lib/libg++/g++-include/Fix24.cc new file mode 100644 index 00000000000..22e23dcbcf2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix24.cc @@ -0,0 +1,327 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +// +// Fix24.cc : fixed precision class support functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Fix24.h> + +// 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 * (const Fix24& a, const 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 / (const Fix24& a, const 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 ((unsigned)(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 & ~0xFF); +} + + +Fix48 operator + (const Fix48& f, const 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 - (const Fix48& f, const 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 * (const 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 << (const Fix48& a, int b) +{ + twolongs r; r.u = 0; 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 >> (const Fix48& a, int b) +{ + twolongs r; r.u = 0; 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) const +{ + (*Fix24_overflow_handler)(i); +} + +void Fix48::overflow(twolongs& i) const +{ + (*Fix48_overflow_handler)(i); +} + +void Fix24::range_error(long& i) const +{ + (*Fix24_range_error_handler)(i); +} + +void Fix48::range_error(twolongs& i) const +{ + (*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(); } + diff --git a/gnu/lib/libg++/g++-include/Fix24.h b/gnu/lib/libg++/g++-include/Fix24.h new file mode 100644 index 00000000000..6de676c08eb --- /dev/null +++ b/gnu/lib/libg++/g++-include/Fix24.h @@ -0,0 +1,599 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Fix24.h,v 1.1 1995/10/18 08:38:16 deraadt Exp $ +*/ + +#ifndef _Fix24_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix24_h 1 + +#include <stream.h> +#include <std.h> + +// extra type definitions + +typedef struct { + long u; + unsigned long l; +} twolongs; + +// constant definitions + +static const int + Fix24_shift = 31; + +static 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.; + +static const unsigned long + Fix24_msb = 0x80000000L, + Fix24_lsb = 0x00000100L, + Fix24_m_max = 0x7fffff00L, + Fix24_m_min = 0x80000000L; + +static 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; + +static const twolongs + Fix48_msb = { 0x80000000L, 0L }, + Fix48_lsb = { 0L, 0x00000100L }, + Fix48_m_max = { 0x7fffff00L, 0xffffff00L }, + Fix48_m_min = { 0x80000000L, 0L }; + +// +// 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() const; + Fix24(long i); + Fix24(int i); + + +public: + Fix24(); + Fix24(const Fix24& f); + Fix24(double d); + Fix24(const Fix48& f); + + ~Fix24(); + + Fix24& operator=(const Fix24& f); + Fix24& operator=(double d); + Fix24& operator=(const Fix48& f); + + friend long& mantissa(Fix24& f); + friend const long& mantissa(const Fix24& f); + friend double value(const Fix24& f); + + Fix24 operator + () const; + Fix24 operator - () const; + + friend Fix24 operator + (const Fix24& f, const Fix24& g); + friend Fix24 operator - (const Fix24& f, const Fix24& g); + friend Fix48 operator * (const Fix24& f, const Fix24& g); + friend Fix24 operator * (const Fix24& f, int g); + friend Fix24 operator * (int g, const Fix24& f); + friend Fix24 operator / (const Fix24& f, const Fix24& g); + friend Fix24 operator << (const Fix24& f, int b); + friend Fix24 operator >> (const Fix24& f, int b); + + Fix24& operator += (const Fix24& f); + Fix24& operator -= (const Fix24& f); + Fix24& operator *= (const Fix24& f); + Fix24& operator *= (int b); + Fix24& operator /= (const Fix24& f); + + Fix24& operator <<=(int b); + Fix24& operator >>=(int b); + + friend int operator == (const Fix24& f, const Fix24& g); + friend int operator != (const Fix24& f, const Fix24& g); + friend int operator >= (const Fix24& f, const Fix24& g); + friend int operator <= (const Fix24& f, const Fix24& g); + friend int operator > (const Fix24& f, const Fix24& g); + friend int operator < (const Fix24& f, const Fix24& g); + + friend istream& operator >> (istream& s, Fix24& f); + friend ostream& operator << (ostream& s, const Fix24& f); + + void overflow(long&) const; + void range_error(long&) const; +}; + + +// +// 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() const; + Fix48(twolongs i); + +public: + Fix48(); + Fix48(const Fix48& f); + Fix48(const Fix24& f); + Fix48(double d); + ~Fix48(); + + Fix48& operator = (const Fix48& f); + Fix48& operator = (const Fix24& f); + Fix48& operator = (double d); + + friend twolongs& mantissa(Fix48& f); + friend const twolongs& mantissa(const Fix48& f); + friend double value(const Fix48& f); + + Fix48 operator + () const; + Fix48 operator - () const; + + friend Fix48 operator + (const Fix48& f, const Fix48& g); + friend Fix48 operator - (const Fix48& f, const Fix48& g); + friend Fix48 operator * (const Fix48& f, int g); + friend Fix48 operator * (int g, const Fix48& f); + friend Fix48 operator << (const Fix48& f, int b); + friend Fix48 operator >> (const Fix48& f, int b); + + friend Fix48 operator * (const Fix24& f, const Fix24& g); + + Fix48& operator += (const Fix48& f); + Fix48& operator -= (const Fix48& f); + Fix48& operator *= (int b); + Fix48& operator <<=(int b); + Fix48& operator >>=(int b); + + friend int operator == (const Fix48& f, const Fix48& g); + friend int operator != (const Fix48& f, const Fix48& g); + friend int operator >= (const Fix48& f, const Fix48& g); + friend int operator <= (const Fix48& f, const Fix48& g); + friend int operator > (const Fix48& f, const Fix48& g); + friend int operator < (const Fix48& f, const Fix48& g); + + friend istream& operator >> (istream& s, Fix48& f); + friend ostream& operator << (ostream& s, const Fix48& f); + + void overflow(twolongs& i) const; + void range_error(twolongs& i) const; +}; + + +// 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 + +#if defined(SHORT_NAMES) || defined(VMS) +#define set_overflow_handler sohndl +#define set_range_error_handler srnghdl +#endif + +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&); + + +inline Fix24::~Fix24() {} + +inline Fix24::Fix24(long i) +{ + m = i; +} + +inline Fix24::Fix24(int i) +{ + m = i; +} + +inline Fix24::operator double() const +{ + return Fix24_div * m; +} + +inline Fix24::Fix24() +{ + m = 0; +} + +inline Fix24::Fix24(const Fix24& f) +{ + m = f.m; +} + +inline Fix24::Fix24(double d) +{ + m = assign(d); +} + +inline Fix24::Fix24(const Fix48& f) +{ + m = f.m.u; +} + +inline Fix24& Fix24::operator=(const Fix24& f) +{ + m = f.m; + return *this; +} + +inline Fix24& Fix24::operator=(double d) +{ + m = assign(d); + return *this; +} + +inline Fix24& Fix24::operator=(const Fix48& f) +{ + m = f.m.u; + return *this; +} + +inline long& mantissa(Fix24& f) +{ + return f.m; +} + +inline const long& mantissa(const Fix24& f) +{ + return f.m; +} + +inline double value(const Fix24& f) +{ + return double(f); +} + +inline Fix24 Fix24::operator+() const +{ + return m; +} + +inline Fix24 Fix24::operator-() const +{ + return -m; +} + +inline Fix24 operator+(const Fix24& f, const 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-(const Fix24& f, const 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*(const Fix24& a, int b) +{ + return a.m * b; +} + +inline Fix24 operator*(int b, const Fix24& a) +{ + return a * b; +} + +inline Fix24 operator<<(const Fix24& a, int b) +{ + return a.m << b; +} + +inline Fix24 operator>>(const Fix24& a, int b) +{ + return (a.m >> b) & 0xffffff00L; +} + +inline Fix24& Fix24:: operator+=(const Fix24& f) +{ + return *this = *this + f; +} + +inline Fix24& Fix24:: operator-=(const Fix24& f) +{ + return *this = *this - f; +} + +inline Fix24& Fix24::operator*=(const Fix24& f) +{ + return *this = *this * f; +} + +inline Fix24& Fix24:: operator/=(const 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==(const Fix24& f, const Fix24& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix24& f, const Fix24& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix24& f, const Fix24& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix24& f, const Fix24& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix24& f, const Fix24& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix24& f, const 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, const Fix24& f) +{ + return s << double(f); +} + +inline Fix48::~Fix48() {} + +inline Fix48::Fix48(twolongs i) +{ + m = i; +} + +inline Fix48:: operator double() const +{ +/* + * 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(const Fix48& f) +{ + m = f.m; +} + +inline Fix48::Fix48(const Fix24& f) +{ + m.u = f.m; + m.l = 0; +} + +inline Fix48::Fix48(double d) +{ + m = assign(d); +} + +inline Fix48& Fix48::operator=(const Fix48& f) +{ + m = f.m; + return *this; +} + +inline Fix48& Fix48::operator=(const 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 const twolongs& mantissa(const Fix48& f) +{ + return f.m; +} + +inline double value(const Fix48& f) +{ + return double(f); +} + +inline Fix48 Fix48::operator+() const +{ + return m; +} + +inline Fix48 Fix48::operator-() const +{ + 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, const Fix48& a) +{ + return a * b; +} + +inline Fix48& Fix48::operator+=(const Fix48& f) +{ + return *this = *this + f; +} + +inline Fix48& Fix48::operator-=(const 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==(const Fix48& f, const Fix48& g) +{ + return f.m.u == g.m.u && f.m.l == g.m.l; +} + +inline int operator!=(const Fix48& f, const Fix48& g) +{ + return f.m.u != g.m.u || f.m.l != g.m.l; +} + +inline int operator>=(const Fix48& f, const Fix48& g) +{ + return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l); +} + +inline int operator<=(const Fix48& f, const Fix48& g) +{ + return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l); +} + +inline int operator>(const Fix48& f, const Fix48& g) +{ + return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l); +} + +inline int operator<(const Fix48& f, const 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, const Fix48& f) +{ + return s << double(f); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/Geom.cc b/gnu/lib/libg++/g++-include/Geom.cc new file mode 100644 index 00000000000..0353738a3dd --- /dev/null +++ b/gnu/lib/libg++/g++-include/Geom.cc @@ -0,0 +1,30 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Geom.h> + +double Geometric::operator()() +{ + int samples; + for (samples = 1; pGenerator -> asDouble() < pMean; samples++); + return((double) samples); +} + diff --git a/gnu/lib/libg++/g++-include/Geom.h b/gnu/lib/libg++/g++-include/Geom.h new file mode 100644 index 00000000000..ba920184b79 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Geom.h @@ -0,0 +1,55 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Geom.h,v 1.1 1995/10/18 08:38:16 deraadt Exp $ +*/ + +#ifndef _Geometric_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Geometric_h + +#include <Random.h> + +class Geometric: public Random { +protected: + double pMean; +public: + Geometric(double mean, RNG *gen); + + double mean(); + double mean(double x); + + virtual double operator()(); + +}; + + +inline Geometric::Geometric(double mean, RNG *gen) : Random(gen) +{ + pMean = mean; +} + + +inline double Geometric::mean() { return pMean; } +inline double Geometric::mean(double x) { + double tmp = pMean; pMean = x; return tmp; +} + + +#endif diff --git a/gnu/lib/libg++/g++-include/GetOpt.cc b/gnu/lib/libg++/g++-include/GetOpt.cc new file mode 100644 index 00000000000..16c647ddb6c --- /dev/null +++ b/gnu/lib/libg++/g++-include/GetOpt.cc @@ -0,0 +1,253 @@ +/* +Getopt for GNU. +Copyright (C) 1987, 1989 Free Software Foundation, Inc. + +(Modified by Douglas C. Schmidt for use with GNU G++.) +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +/* AIX requires the alloca decl to be the first thing in the file. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#elif defined(sparc) +#include <alloca.h> +extern "C" void *__builtin_alloca(...); +#elif defined(_AIX) +#pragma alloca +#else +char *alloca (); +#endif +#include <GetOpt.h> + +char* GetOpt::nextchar = 0; +int GetOpt::first_nonopt = 0; +int GetOpt::last_nonopt = 0; + +GetOpt::GetOpt (int argc, char **argv, const char *optstring) + :opterr (1), nargc (argc), nargv (argv), noptstring (optstring) +{ + /* 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. */ + + 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. */ + + memcpy (temp, &argv[first_nonopt], nonopts_size); + memcpy (&argv[first_nonopt], &argv[last_nonopt], + (optind - last_nonopt) * sizeof (char *)); + memcpy (&argv[first_nonopt + optind - last_nonopt], temp, + 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 *) strchr (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; + } +} diff --git a/gnu/lib/libg++/g++-include/GetOpt.h b/gnu/lib/libg++/g++-include/GetOpt.h new file mode 100644 index 00000000000..fa5cd2e8094 --- /dev/null +++ b/gnu/lib/libg++/g++-include/GetOpt.h @@ -0,0 +1,130 @@ +/* Getopt for GNU. + Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + (Modified by Douglas C. Schmidt for use with GNU G++.) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: GetOpt.h,v 1.1 1995/10/18 08:38:16 deraadt Exp $ +*/ + +/* 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 +#ifdef __GNUG__ +#pragma interface +#endif +#define GetOpt_h 1 + +#include <std.h> +#include <stdio.h> + +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. */ + + enum OrderingEnum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; + OrderingEnum 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; + const char *noptstring; + + GetOpt (int argc, char **argv, const char *optstring); + int operator () (void); +}; + +#endif diff --git a/gnu/lib/libg++/g++-include/HypGeom.cc b/gnu/lib/libg++/g++-include/HypGeom.cc new file mode 100644 index 00000000000..50d95867d3d --- /dev/null +++ b/gnu/lib/libg++/g++-include/HypGeom.cc @@ -0,0 +1,30 @@ + +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <HypGeom.h> + +double HyperGeometric::operator()() +{ + double d = (pGenerator -> asDouble() > pP) ? (1.0 - pP) : (pP); + return(-pMean * log(pGenerator -> asDouble()) / (2.0 * d) ); +} + diff --git a/gnu/lib/libg++/g++-include/HypGeom.h b/gnu/lib/libg++/g++-include/HypGeom.h new file mode 100644 index 00000000000..97e59b98460 --- /dev/null +++ b/gnu/lib/libg++/g++-include/HypGeom.h @@ -0,0 +1,73 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: HypGeom.h,v 1.1 1995/10/18 08:38:16 deraadt Exp $ +*/ + +#ifndef _HyperGeometric_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _HyperGeometric_h + +#include <Random.h> + +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()(); +}; + + +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) +: Random(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 diff --git a/gnu/lib/libg++/g++-include/Integer.cc b/gnu/lib/libg++/g++-include/Integer.cc new file mode 100644 index 00000000000..f4ec47e6699 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Integer.cc @@ -0,0 +1,2423 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <ctype.h> +#include <float.h> +#include <limits.h> +#include <math.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include <Integer.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#define HUGE_VAL DBL_MAX +#endif +#endif + +/* + 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 (sizeof(short) * CHAR_BIT) +#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 ((unsigned)(((sizeof(long) + sizeof(short) - 1) / sizeof(short)))) +#define CHAR_PER_LONG ((unsigned)sizeof(long)) + +/* + 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 + +IntRep _ZeroRep = {1, 0, 1, {0}}; +IntRep _OneRep = {1, 0, 1, {1}}; +IntRep _MinusOneRep = {1, 0, 0, {1}}; + + +// 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 && !STATIC_IntRep(old)) delete old; + return rep; +} + +// allocate and clear + +IntRep* Icalloc(IntRep* old, int newlen) +{ + IntRep* rep; + if (old == 0 || newlen > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) 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; + if (!STATIC_IntRep(old)) 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 && !STATIC_IntRep(old)) 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) +{ + int newsgn = (x >= 0); + IntRep* rep = Icopy_ulong(old, newsgn ? x : -x); + rep->sgn = newsgn; + return rep; +} + +IntRep* Icopy_ulong(IntRep* old, unsigned long x) +{ + unsigned short src[SHORT_PER_LONG]; + + unsigned short srclen = 0; + while (x != 0) + { + src[srclen++] = extract(x); + x = down(x); + } + + IntRep* rep; + if (old == 0 || srclen > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + rep = Inew(srclen); + } + else + rep = old; + + rep->len = srclen; + rep->sgn = I_POSITIVE; + + scpy(src, rep->s, srclen); + + return rep; +} + +// special case for zero -- it's worth it! + +IntRep* Icopy_zero(IntRep* old) +{ + if (old == 0 || STATIC_IntRep(old)) + return &_ZeroRep; + + old->len = 0; + old->sgn = I_POSITIVE; + + return old; +} + +// special case for 1 or -1 + +IntRep* Icopy_one(IntRep* old, int newsgn) +{ + if (old == 0 || 1 > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + return newsgn==I_NEGATIVE ? &_MinusOneRep : &_OneRep; + } + + old->sgn = newsgn; + old->len = 1; + old->s[0] = 1; + + return old; +} + +// convert to a legal two's complement long if possible +// if too big, return most negative/positive value + +long Itolong(const IntRep* rep) +{ + if ((unsigned)(rep->len) > (unsigned)(SHORT_PER_LONG)) + return (rep->sgn == I_POSITIVE) ? LONG_MAX : LONG_MIN; + else if (rep->len == 0) + return 0; + else if ((unsigned)(rep->len) < (unsigned)(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) ? LONG_MAX : LONG_MIN; + 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 LONG_MIN & LONG_MAX + +int Iislong(const IntRep* rep) +{ + unsigned int l = rep->len; + if (l < SHORT_PER_LONG) + return 1; + else if (l > SHORT_PER_LONG) + return 0; + else if ((unsigned)(rep->s[SHORT_PER_LONG - 1]) < (unsigned)(I_MINNUM)) + return 1; + else if (rep->sgn == I_NEGATIVE && rep->s[SHORT_PER_LONG - 1] == I_MINNUM) + { + for (unsigned 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 = DBL_MAX / 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_VAL : HUGE_VAL; + 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 = DBL_MAX / 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 = q.as_double(); + + if (d1 >= DBL_MAX || d1 <= -DBL_MAX || sign(r) == 0) + return d1; + else // use as much precision as available for fractional part + { + double d2 = 0.0; + double d3 = 0.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 + 1.0 == d2) // out of precision when we get here + { + 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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, yy->s, yl, q->s, ql); + + if (yy != y && !STATIC_IntRep(yy)) delete yy; + if (!STATIC_IntRep(r)) 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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, ys, yl, q->s, ql); + + if (!STATIC_IntRep(r)) 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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + 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); + if (!STATIC_IntRep(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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, yy->s, yl, q->s, ql); + + if (yy != y && !STATIC_IntRep(yy)) 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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + do_divide(r->s, yy->s, yl, 0, xl - yl + 1); + + if (yy != y && !STATIC_IntRep(yy)) 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 = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + 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; + int xl = x.rep ? x.rep->len : 0; + if (xl <= bw) + 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) + { + if (x.rep == 0) + x.rep = &_ZeroRep; + else + { + int bw = (unsigned long)b / I_SHIFT; + int sw = (unsigned long)b % I_SHIFT; + if (x.rep->len > bw) + 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); + } + } + if (!STATIC_IntRep(t)) delete t; + if (!STATIC_IntRep(v)) delete v; + if (k != 0) u = lshift(u, k, u); + return u; +} + + + +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); + } + if (!STATIC_IntRep(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; +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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; +} + +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); +} + +#else +Integer sqrt(const Integer& x) +{ + Integer 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 r; +} + +Integer lcm(const Integer& x, const Integer& y) +{ + Integer 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); + return r; +} + +#endif + + + +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); + ++s; + } + r->sgn = sgn; + } + return r; +} + + + +extern AllocRing _libgxx_fmtq; + +char* Itoa(const IntRep* x, int base, int width) +{ + int fmtlen = (x->len + 1) * I_SHIFT / lg(base) + 4 + width; + char* fmtbase = (char *) _libgxx_fmtq.alloc(fmtlen); + char* f = cvtItoa(x, fmtbase, fmtlen, base, 0, width, 0, ' ', 'X', 0); + return f; +} + +ostream& operator << (ostream& s, const Integer& y) +{ +#ifdef _OLD_STREAMS + return s << Itoa(y.rep); +#else + if (s.opfx()) + { + int base = (s.flags() & ios::oct) ? 8 : (s.flags() & ios::hex) ? 16 : 10; + int width = s.width(); + y.printon(s, base, width); + } + return s; +#endif +} + +void Integer::printon(ostream& s, int base /* =10 */, int width /* =0 */) const +{ + int align_right = !(s.flags() & ios::left); + int showpos = s.flags() & ios::showpos; + int showbase = s.flags() & ios::showbase; + char fillchar = s.fill(); + char Xcase = (s.flags() & ios::uppercase)? 'X' : 'x'; + const IntRep* x = rep; + int fmtlen = (x->len + 1) * I_SHIFT / lg(base) + 4 + width; + char* fmtbase = new char[fmtlen]; + char* f = cvtItoa(x, fmtbase, fmtlen, base, showbase, width, align_right, + fillchar, Xcase, showpos); + s.write(f, fmtlen); + delete fmtbase; +} + +char* cvtItoa(const IntRep* x, char* fmt, int& fmtlen, int base, int showbase, + int width, int align_right, char fillchar, char Xcase, + int showpos) +{ + char* e = fmt + fmtlen - 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; + } + if (!STATIC_IntRep(z)) 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 (base == 8 && showbase) + *--s = '0'; + else if (base == 16 && showbase) + { + *--s = Xcase; + *--s = '0'; + } + if (x->sgn == I_NEGATIVE) *--s = '-'; + else if (showpos) *--s = '+'; + int w = e - s - 1; + if (!align_right || w >= width) + { + while (w++ < width) + *--s = fillchar; + fmtlen = e - s - 1; + return s; + } + else + { + char* p = fmt; + int gap = s - p; + for (char* t = s; *t != 0; ++t, ++p) *p = *t; + while (w++ < width) *p++ = fillchar; + *p = 0; + fmtlen = p - fmt; + return fmt; + } +} + +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) +{ +#ifdef _OLD_STREAMS + if (!s.good()) + return s; +#else + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); + return s; + } +#endif + s >> ws; + if (!s.good()) + { + s.clear(ios::failbit|s.rdstate()); + return s; + } + +#ifdef _OLD_STREAMS + int know_base = 0; + int base = 10; +#else + int know_base = s.flags() & (ios::oct | ios::hex | ios::dec); + int base = (s.flags() & ios::oct) ? 8 : (s.flags() & ios::hex) ? 16 : 10; +#endif + + int got_one = 0; + char sgn = 0; + char ch; + y.rep = Icopy_zero(y.rep); + + while (s.get(ch)) + { + if (ch == '-') + { + if (sgn == 0) + sgn = '-'; + else + break; + } + else if (!know_base & !got_one && ch == '0') + base = 8, got_one = 1; + else if (!know_base & !got_one && base == 8 && (ch == 'X' || ch == 'x')) + base = 16; + else if (base == 8) + { + if (ch >= '0' && ch <= '7') + { + long digit = ch - '0'; + y <<= 3; + y += digit; + got_one = 1; + } + else + break; + } + else if (base == 16) + { + long digit; + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = base; + if (digit < base) + { + y <<= 4; + y += digit; + got_one = 1; + } + else + break; + } + else if (base == 10) + { + if (ch >= '0' && ch <= '9') + { + long digit = ch - '0'; + y *= 10; + y += digit; + got_one = 1; + } + else + break; + } + else + abort(); // can't happen for now + } + if (s.good()) + s.putback(ch); + if (!got_one) + s.clear(ios::failbit|s.rdstate()); + + if (sgn == '-') + y.negate(); + + return s; +} + +int Integer::OK() const +{ + if (rep != 0) + { + int l = rep->len; + int s = rep->sgn; + int v = l <= rep->sz || STATIC_IntRep(rep); // length within bounds + v &= s == 0 || s == 1; // legal sign + Icheck(rep); // and correctly adjusted + v &= rep->len == l; + v &= rep->sgn == s; + if (v) + return v; + } + error("invariant failure"); + return 0; +} + +void Integer::error(const char* msg) const +{ + (*lib_error_handler)("Integer", msg); +} + diff --git a/gnu/lib/libg++/g++-include/Integer.h b/gnu/lib/libg++/g++-include/Integer.h new file mode 100644 index 00000000000..7f044c1af9e --- /dev/null +++ b/gnu/lib/libg++/g++-include/Integer.h @@ -0,0 +1,1104 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Integer.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Integer_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Integer_h 1 + +#include <iostream.h> + +struct IntRep // internal Integer representations +{ + unsigned short len; // current length + unsigned short sz; // allocated space (0 means static). + short sgn; // 1 means >= 0; 0 means < 0 + unsigned short s[1]; // represented as ushort array starting here +}; + +// True if REP is staticly (or manually) allocated, +// and should not be deleted by an Integer destructor. +#define STATIC_IntRep(rep) ((rep)->sz==0) + +extern IntRep* Ialloc(IntRep*, const unsigned short *, int, int, int); +extern IntRep* Icalloc(IntRep*, int); +extern IntRep* Icopy_ulong(IntRep*, unsigned long); +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 char* cvtItoa(const IntRep* x, char* fmt, int& fmtlen, int base, + int showbase, int width, int align_right, + char fillchar, char Xcase, int showpos); +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*); + +extern IntRep _ZeroRep, _OneRep, _MinusOneRep; + +class Integer +{ +protected: + IntRep* rep; +public: + Integer(); + Integer(int); + Integer(long); + Integer(unsigned long); + Integer(IntRep*); + 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); // min + 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 { return Iislong(rep); } + int fits_in_double() const { return Iisdouble(rep); } + +#if 0 + // There two operators cause a number of ambiguities. + operator long() const { return Itolong(rep); } + operator double() const { return Itodouble(rep); } +#endif + long as_long() const { return Itolong(rep); } + double as_double() const { return Itodouble(rep); } + + friend char* Itoa(const Integer& x, int base = 10, int width = 0); + friend Integer atoI(const char* s, int base = 10); + void printon(ostream& s, int base = 10, int width = 0) const; + + friend istream& operator >> (istream& s, Integer& y); + friend ostream& operator << (ostream& s, const Integer& y); + +// error detection + + int initialized() const; + void error(const char* msg) const; + int OK() const; +}; + + +// (These are declared inline) + + 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 + +inline Integer::Integer() :rep(&_ZeroRep) {} + +inline Integer::Integer(IntRep* r) :rep(r) {} + +inline Integer::Integer(int y) :rep(Icopy_long(0, (long)y)) {} + +inline Integer::Integer(long y) :rep(Icopy_long(0, y)) {} + +inline Integer::Integer(unsigned long y) :rep(Icopy_ulong(0, y)) {} + +inline Integer::Integer(const Integer& y) :rep(Icopy(0, y.rep)) {} + +inline Integer::~Integer() { if (rep && !STATIC_IntRep(rep)) 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 int Integer::initialized() const +{ + return rep != 0; +} + +// 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, Itolong(y.rep), 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 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 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 void Integer::operator *= (const Integer& y) +{ + mul(*this, y, *this); +} + +inline void Integer::operator *= (long y) +{ + mul(*this, y, *this); +} + + +inline void Integer::operator &= (const Integer& y) +{ + and(*this, y, *this); +} + +inline void Integer::operator &= (long y) +{ + and(*this, y, *this); +} + +inline void Integer::operator |= (const Integer& y) +{ + or(*this, y, *this); +} + +inline void Integer::operator |= (long y) +{ + or(*this, y, *this); +} + + +inline void Integer::operator ^= (const Integer& y) +{ + xor(*this, y, *this); +} + +inline void Integer::operator ^= (long y) +{ + xor(*this, y, *this); +} + + + +inline void Integer::operator /= (const Integer& y) +{ + div(*this, y, *this); +} + +inline void Integer::operator /= (long y) +{ + div(*this, y, *this); +} + + +inline void Integer::operator <<= (const Integer& y) +{ + lshift(*this, y, *this); +} + +inline void Integer::operator <<= (long y) +{ + lshift(*this, y, *this); +} + + +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; +} + +inline Integer operator >? (const Integer& x, const Integer& y) +{ + return (compare(x.rep, y.rep) >= 0)? x : y; +} +#endif + + +inline void Integer::abs() +{ + ::abs(*this, *this); +} + +inline void Integer::negate() +{ + ::negate(*this, *this); +} + + +inline void Integer::complement() +{ + ::complement(*this, *this); +} + + +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 long lg(const Integer& x) +{ + return lg(x.rep); +} + +// constructive operations + +#if defined(__GNUG__) && !defined(NO_NRV) + +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 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 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 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 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 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 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 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 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 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 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 Integer operator - (const Integer& x) return r +{ + negate(x, r); +} + +inline Integer operator ~ (const Integer& x) return r +{ + complement(x, r); +} + +inline Integer atoI(const char* s, int base) return r +{ + r.rep = atoIntRep(s, base); +} + +inline Integer gcd(const Integer& x, const Integer& y) return r +{ + r.rep = gcd(x.rep, y.rep); +} + +#else /* NO_NRV */ + +inline Integer operator + (const Integer& x, const Integer& y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator + (const Integer& x, long y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator + (long x, const Integer& y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator - (const Integer& x, const Integer& y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator - (const Integer& x, long y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator - (long x, const Integer& y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator * (const Integer& x, const Integer& y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer operator * (const Integer& x, long y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer operator * (long x, const Integer& y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer sqr(const Integer& x) +{ + Integer r; mul(x, x, r); return r; +} + +inline Integer operator & (const Integer& x, const Integer& y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator & (const Integer& x, long y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator & (long x, const Integer& y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator | (const Integer& x, const Integer& y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator | (const Integer& x, long y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator | (long x, const Integer& y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator ^ (const Integer& x, const Integer& y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator ^ (const Integer& x, long y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator ^ (long x, const Integer& y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator / (const Integer& x, const Integer& y) +{ + Integer r; div(x, y, r); return r; +} + +inline Integer operator / (const Integer& x, long y) +{ + Integer r; div(x, y, r); return r; +} + +inline Integer operator % (const Integer& x, const Integer& y) +{ + Integer r; mod(x, y, r); return r; +} + +inline Integer operator % (const Integer& x, long y) +{ + Integer r; mod(x, y, r); return r; +} + +inline Integer operator << (const Integer& x, const Integer& y) +{ + Integer r; lshift(x, y, r); return r; +} + +inline Integer operator << (const Integer& x, long y) +{ + Integer r; lshift(x, y, r); return r; +} + +inline Integer operator >> (const Integer& x, const Integer& y) +{ + Integer r; rshift(x, y, r); return r; +} + +inline Integer operator >> (const Integer& x, long y) +{ + Integer r; rshift(x, y, r); return r; +} + +inline Integer pow(const Integer& x, long y) +{ + Integer r; pow(x, y, r); return r; +} + +inline Integer Ipow(long x, long y) +{ + Integer r(x); pow(r, y, r); return r; +} + +inline Integer pow(const Integer& x, const Integer& y) +{ + Integer r; pow(x, y, r); return r; +} + + + +inline Integer abs(const Integer& x) +{ + Integer r; abs(x, r); return r; +} + +inline Integer operator - (const Integer& x) +{ + Integer r; negate(x, r); return r; +} + +inline Integer operator ~ (const Integer& x) +{ + Integer r; complement(x, r); return r; +} + +inline Integer atoI(const char* s, int base) +{ + Integer r; r.rep = atoIntRep(s, base); return r; +} + +inline Integer gcd(const Integer& x, const Integer& y) +{ + Integer r; r.rep = gcd(x.rep, y.rep); return r; +} + +#endif /* NO_NRV */ + +inline void Integer::operator %= (const Integer& y) +{ + *this = *this % y; // mod(*this, y, *this) doesn't work. +} + +inline void Integer::operator %= (long y) +{ + *this = *this % y; // mod(*this, y, *this) doesn't work. +} +#endif /* !_Integer_h */ diff --git a/gnu/lib/libg++/g++-include/LogNorm.cc b/gnu/lib/libg++/g++-include/LogNorm.cc new file mode 100644 index 00000000000..8adc86cbdbd --- /dev/null +++ b/gnu/lib/libg++/g++-include/LogNorm.cc @@ -0,0 +1,36 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Normal.h> + +#include <LogNorm.h> + +// +// See Simulation, Modelling & Analysis by Law & Kelton, pp260 +// +// + +double LogNormal::operator()() +{ + return( pow(M_E, this->Normal::operator()() ) ); +} + + diff --git a/gnu/lib/libg++/g++-include/LogNorm.h b/gnu/lib/libg++/g++-include/LogNorm.h new file mode 100644 index 00000000000..2e9454cadc2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/LogNorm.h @@ -0,0 +1,81 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: LogNorm.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _LogNormal_h +#ifdef __GNUG__ +#pragma interface +#endif +#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); + double mean(); + double mean(double x); + double variance(); + double variance(double x); + virtual double operator()(); +}; + + +inline void LogNormal::setState() +{ + double m2 = logMean * logMean; + pMean = log(m2 / sqrt(logVariance + m2) ); +// from ch@heike.informatik.uni-dortmund.de: +// (was pVariance = log((sqrt(logVariance + m2)/m2 )); ) + pStdDev = sqrt(log((logVariance + m2)/m2 )); +} + +inline LogNormal::LogNormal(double mean, double variance, RNG *gen) + : Normal(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 diff --git a/gnu/lib/libg++/g++-include/MLCG.cc b/gnu/lib/libg++/g++-include/MLCG.cc new file mode 100644 index 00000000000..74836c65afb --- /dev/null +++ b/gnu/lib/libg++/g++-include/MLCG.cc @@ -0,0 +1,103 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#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); +} + diff --git a/gnu/lib/libg++/g++-include/MLCG.h b/gnu/lib/libg++/g++-include/MLCG.h new file mode 100644 index 00000000000..b0a3f6fcb42 --- /dev/null +++ b/gnu/lib/libg++/g++-include/MLCG.h @@ -0,0 +1,90 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: MLCG.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _MLCG_h +#define _MLCG_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <RNG.h> +#include <math.h> + +// +// 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 diff --git a/gnu/lib/libg++/g++-include/Makefile b/gnu/lib/libg++/g++-include/Makefile new file mode 100644 index 00000000000..f9b55ce74b5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Makefile @@ -0,0 +1,31 @@ +# $Id: Makefile,v 1.1 1995/10/18 08:38:17 deraadt Exp $ + +LIB= g++ + +SRCS= AllocRing.cc Obstack.cc builtin.cc \ + regex.cc Regex.cc String.cc Integer.cc Rational.cc Complex.cc Random.cc \ + BitSet.cc BitString.cc LogNorm.cc SmplHist.cc SmplStat.cc \ + Normal.cc NegExp.cc Weibull.cc Erlang.cc DiscUnif.cc \ + Uniform.cc Poisson.cc HypGeom.cc Geom.cc Binomial.cc \ + RNG.cc ACG.cc MLCG.cc RndInt.cc \ + Fix.cc Fix16.cc Fix24.cc CursesW.cc GetOpt.cc $(EH_FILES) \ + new.cc chr.cc dtoa.cc error.cc gcd.cc hash.cc \ + lg.cc fmtq.cc ioob.cc pow.cc sqrt.cc str.cc timer.cc \ + math.cc compare.cc SLList.cc DLList.cc \ + streambuf.C stdstrbufs.C iostream.C stdstreams.C \ + strstream.C indstream.C PlotFile.C SFile.C fstream.C \ + parsestream.C stream.C makebuf.C editbuf.C filebuf.C \ + sgetline.C igetline.C igetsb.C procbuf.C sbufvform.C \ + sbufvscan.C stdiostream.C floatconv.C outfloat.C iomanip.C + +CXXFLAGS+= -nostdinc++ -I$(.CURDIR)/../g++-include \ + -I$(.CURDIR)/../iostream +CFLAGS+= -I$(.CURDIR) +LDADD= ${DESTDIR}/usr/lib/c++rt0.o -lcurses +DPADD= ${DESTDIR}/usr/lib/c++rt0.o ${LIBCURSES} +NOMAN= noman +.PATH: $(.CURDIR)/../iostream +LIBCURSES!= printf "xxx:\n\techo \$${LIBCURSES}\n.include <bsd.prog.mk>" |\ + $(MAKE) -r -s -f - xxx + +.include <bsd.lib.mk> diff --git a/gnu/lib/libg++/g++-include/NegExp.cc b/gnu/lib/libg++/g++-include/NegExp.cc new file mode 100644 index 00000000000..8bd6d0514d7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/NegExp.cc @@ -0,0 +1,28 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <NegExp.h> + +double NegativeExpntl::operator()() +{ + return(-pMean * log(pGenerator -> asDouble())); +} + diff --git a/gnu/lib/libg++/g++-include/NegExp.h b/gnu/lib/libg++/g++-include/NegExp.h new file mode 100644 index 00000000000..f5574a17aee --- /dev/null +++ b/gnu/lib/libg++/g++-include/NegExp.h @@ -0,0 +1,58 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: NegExp.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _NegativeExpntl_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _NegativeExpntl_h 1 + + +// +// Negative Exponential Random Numbers +// +// + +#include <Random.h> + +class NegativeExpntl: public Random { +protected: + double pMean; +public: + NegativeExpntl(double xmean, RNG *gen); + double mean(); + double mean(double x); + + virtual double operator()(); +}; + + +inline NegativeExpntl::NegativeExpntl(double xmean, RNG *gen) +: Random(gen) { + pMean = xmean; +} + +inline double NegativeExpntl::mean() { return pMean; } +inline double NegativeExpntl::mean(double x) { + double t = pMean; pMean = x; + return t; +} + +#endif diff --git a/gnu/lib/libg++/g++-include/Normal.cc b/gnu/lib/libg++/g++-include/Normal.cc new file mode 100644 index 00000000000..bae43e10553 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Normal.cc @@ -0,0 +1,60 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Normal.h> +// +// 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); + } + } + } +} + diff --git a/gnu/lib/libg++/g++-include/Normal.h b/gnu/lib/libg++/g++-include/Normal.h new file mode 100644 index 00000000000..499ecc38cdb --- /dev/null +++ b/gnu/lib/libg++/g++-include/Normal.h @@ -0,0 +1,69 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Normal.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Normal_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Normal_h + +#include <Random.h> + +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()(); +}; + + +inline Normal::Normal(double xmean, double xvariance, RNG *gen) +: Random(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 diff --git a/gnu/lib/libg++/g++-include/Obstack.cc b/gnu/lib/libg++/g++-include/Obstack.cc new file mode 100644 index 00000000000..f748eb4df83 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Obstack.cc @@ -0,0 +1,112 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <values.h> +#include <builtin.h> +#include <Obstack.h> + +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 [] (char*)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; + + memcpy((void*)new_chunk->contents, (void*)objectbase, 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; +} diff --git a/gnu/lib/libg++/g++-include/Obstack.h b/gnu/lib/libg++/g++-include/Obstack.h new file mode 100644 index 00000000000..2467a8ad862 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Obstack.h @@ -0,0 +1,217 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Obstack.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Obstack_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Obstack_h 1 + +#include <std.h> + +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 +}; + + +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); + memcpy(nextfree, data, size); + nextfree += size; +} + +inline void Obstack:: grow(const void* data, int size, char terminator) +{ + if (nextfree+size+1 > chunklimit) + newchunk(size+1); + memcpy(nextfree, data, size); + nextfree += size; + *(nextfree)++ = terminator; +} + +inline void Obstack:: grow(const char* s) +{ + grow((const 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((const 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 diff --git a/gnu/lib/libg++/g++-include/Pix.h b/gnu/lib/libg++/g++-include/Pix.h new file mode 100644 index 00000000000..c4a5289ddd5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Pix.h @@ -0,0 +1,6 @@ +/* $Id: Pix.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ */ + +#ifndef _Pix_h +#define _Pix_h 1 +typedef void* Pix; +#endif diff --git a/gnu/lib/libg++/g++-include/Poisson.cc b/gnu/lib/libg++/g++-include/Poisson.cc new file mode 100644 index 00000000000..8d70f1751b9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Poisson.cc @@ -0,0 +1,36 @@ + +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Poisson.h> + +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); +} diff --git a/gnu/lib/libg++/g++-include/Poisson.h b/gnu/lib/libg++/g++-include/Poisson.h new file mode 100644 index 00000000000..190518faa48 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Poisson.h @@ -0,0 +1,54 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Poisson.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Poisson_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Poisson_h + +#include <Random.h> + +class Poisson: public Random { +protected: + double pMean; +public: + Poisson(double mean, RNG *gen); + + double mean(); + double mean(double x); + + virtual double operator()(); +}; + + +inline Poisson::Poisson(double mean, RNG *gen) +: Random(gen) { + pMean = mean; +} + +inline double Poisson::mean() { return pMean; } +inline double Poisson::mean(double x) { + double t = pMean; + pMean = x; + return t; +} + +#endif diff --git a/gnu/lib/libg++/g++-include/RNG.cc b/gnu/lib/libg++/g++-include/RNG.cc new file mode 100644 index 00000000000..568b721898a --- /dev/null +++ b/gnu/lib/libg++/g++-include/RNG.cc @@ -0,0 +1,132 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <values.h> +#include <assert.h> +#include <builtin.h> +#include <RNG.h> + +// These two static fields get initialized by RNG::RNG(). +PrivateRNGSingleType RNG::singleMantissa; +PrivateRNGDoubleType RNG::doubleMantissa; + +// +// 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 + volatile double x = 1.0; // volatile needed when fp hardware used, + // and has greater precision than memory doubles + 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); + + volatile float xx = 1.0; // volatile needed when fp hardware used, + // and has greater precision than memory floats + 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; + } +} + +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 ); +} + +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 ); +} + diff --git a/gnu/lib/libg++/g++-include/RNG.h b/gnu/lib/libg++/g++-include/RNG.h new file mode 100644 index 00000000000..3105b3eb5c0 --- /dev/null +++ b/gnu/lib/libg++/g++-include/RNG.h @@ -0,0 +1,60 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: RNG.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _RNG_h +#define _RNG_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <assert.h> +#include <math.h> + +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(); +}; + +#endif diff --git a/gnu/lib/libg++/g++-include/Random.cc b/gnu/lib/libg++/g++-include/Random.cc new file mode 100644 index 00000000000..572a602cf7a --- /dev/null +++ b/gnu/lib/libg++/g++-include/Random.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Random.h> diff --git a/gnu/lib/libg++/g++-include/Random.h b/gnu/lib/libg++/g++-include/Random.h new file mode 100644 index 00000000000..a92bef88fc0 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Random.h @@ -0,0 +1,57 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Random.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Random_h +#define _Random_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <math.h> +#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 diff --git a/gnu/lib/libg++/g++-include/Rational.cc b/gnu/lib/libg++/g++-include/Rational.cc new file mode 100644 index 00000000000..cef31be4b08 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Rational.cc @@ -0,0 +1,415 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <math.h> +#include <values.h> +#include <builtin.h> +#include <float.h> +#include <Rational.h> + +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(); +} + + + + +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 trunc(const Rational& x) +{ + return x.num / x.den ; +} + + +Rational pow(const Rational& x, const Integer& y) +{ + long yy = y.as_long(); + return pow(x, yy); +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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(); +} + +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; + } +} + +// 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(); + } + } +} + +#else + +Rational operator - (const Rational& x) +{ + Rational r(x); r.negate(); return r; +} + +Rational abs(const Rational& x) +{ + Rational r(x); + if (sign(r.num) < 0) r.negate(); + return r; +} + + +Rational sqr(const Rational& x) +{ + Rational r; + mul(x.num, x.num, r.num); + mul(x.den, x.den, r.den); + r.normalize(); + return r; +} + +Integer floor(const Rational& x) +{ + Integer q; + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) < 0 && sign(r) != 0) --q; + return q; +} + +Integer ceil(const Rational& x) +{ + Integer q; + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) >= 0 && sign(r) != 0) ++q; + return q; +} + +Integer round(const Rational& x) +{ + Integer 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; + } + return q; +} + +Rational pow(const Rational& x, long y) +{ + Rational 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(); + } + } + return r; +} + +#endif + +ostream& operator << (ostream& s, const Rational& y) +{ + if (y.denominator() == 1L) + s << y.numerator(); + else + { + s << y.numerator(); + s << "/"; + s << y.denominator(); + } + return s; +} + +istream& operator >> (istream& s, Rational& y) +{ +#ifdef _OLD_STREAMS + if (!s.good()) + { + return s; + } +#else + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } +#endif + Integer n = 0; + Integer d = 1; + if (s >> n) + { + char ch = 0; + s.get(ch); + if (ch == '/') + { + s >> d; + } + else + { + s.putback(ch); + } + } + y = Rational(n, d); + return s; +} + +int Rational::OK() const +{ + int v = num.OK() && den.OK(); // have valid num and denom + if (v) + { + v &= sign(den) > 0; // denominator positive; + v &= ucompare(gcd(num, den), _Int_One) == 0; // relatively prime + } + if (!v) error("invariant failure"); + return v; +} + +int +Rational::fits_in_float() const +{ + return Rational (FLT_MIN) <= *this && *this <= Rational (FLT_MAX); +} + +int +Rational::fits_in_double() const +{ + return Rational (DBL_MIN) <= *this && *this <= Rational (DBL_MAX); +} diff --git a/gnu/lib/libg++/g++-include/Rational.h b/gnu/lib/libg++/g++-include/Rational.h new file mode 100644 index 00000000000..45abc7f61ff --- /dev/null +++ b/gnu/lib/libg++/g++-include/Rational.h @@ -0,0 +1,284 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Rational.h,v 1.1 1995/10/18 08:38:17 deraadt Exp $ +*/ + +#ifndef _Rational_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Rational_h 1 + +#include <Integer.h> +#include <math.h> + +class Rational +{ +protected: + Integer num; + Integer den; + + void normalize(); + +public: + Rational(); + Rational(double); + Rational(int n); + Rational(long n); + Rational(int n, int d); + Rational(long n, long d); + Rational(long n, unsigned long d); + Rational(unsigned long n, long d); + Rational(unsigned long n, unsigned long d); + 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); // min + 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, const 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); + + int fits_in_float() const; + int fits_in_double() const; + +// 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 + + void error(const char* msg) const; + int OK() const; + +}; + +typedef Rational RatTmp; // backwards compatibility + +inline Rational::Rational() : num(&_ZeroRep), den(&_OneRep) {} +inline Rational::~Rational() {} + +inline Rational::Rational(const Rational& y) :num(y.num), den(y.den) {} + +inline Rational::Rational(const Integer& n) :num(n), den(&_OneRep) {} + +inline Rational::Rational(const Integer& n, const Integer& d) :num(n),den(d) +{ + normalize(); +} + +inline Rational::Rational(long n) :num(n), den(&_OneRep) { } + +inline Rational::Rational(int n) :num(n), den(&_OneRep) { } + +inline Rational::Rational(long n, long d) :num(n), den(d) { normalize(); } +inline Rational::Rational(int n, int d) :num(n), den(d) { normalize(); } +inline Rational::Rational(long n, unsigned long d) :num(n), den(d) +{ + normalize(); +} +inline Rational::Rational(unsigned long n, long d) :num(n), den(d) +{ + normalize(); +} +inline Rational::Rational(unsigned long n, unsigned 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(); +} + + +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); } + +#ifdef __GNUG__ +inline Rational operator <? (const Rational& x, const Rational& y) +{ + if (compare(x, y) <= 0) return x; else return y; +} + +inline Rational operator >? (const Rational& x, const Rational& y) +{ + if (compare(x, y) >= 0) return x; else return y; +} +#endif + +#if defined(__GNUG__) && !defined(NO_NRV) + +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); +} + +#else /* NO_NRV */ + +inline Rational operator + (const Rational& x, const Rational& y) +{ + Rational r; add(x, y, r); return r; +} + +inline Rational operator - (const Rational& x, const Rational& y) +{ + Rational r; sub(x, y, r); return r; +} + +inline Rational operator * (const Rational& x, const Rational& y) +{ + Rational r; mul(x, y, r); return r; +} + +inline Rational operator / (const Rational& x, const Rational& y) +{ + Rational r; div(x, y, r); return r; +} +#endif + +#endif diff --git a/gnu/lib/libg++/g++-include/Regex.cc b/gnu/lib/libg++/g++-include/Regex.cc new file mode 100644 index 00000000000..d10eaec940a --- /dev/null +++ b/gnu/lib/libg++/g++-include/Regex.cc @@ -0,0 +1,136 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Regex class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <ctype.h> +#include <values.h> +#include <new.h> +#include <builtin.h> + +extern "C" { +#include <regex.h> +} + +#include <Regex.h> + +Regex::~Regex() +{ + if (buf->buffer) free(buf->buffer); + if (buf->fastmap) free(buf->fastmap); + delete(buf); + delete(reg); +} + +Regex::Regex(const char* t, int fast, int bufsize, + const char* transtable) +{ + int tlen = (t == 0)? 0 : strlen(t); + buf = new re_pattern_buffer; + reg = new re_registers; + if (fast) + buf->fastmap = (char*)malloc(256); + else + buf->fastmap = 0; + buf->translate = (char*)transtable; + if (tlen > bufsize) + bufsize = tlen; + buf->allocated = bufsize; + buf->buffer = (char *)malloc(buf->allocated); + char* msg = re_compile_pattern((const 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, (char*)s, p, 0, reg, p); + } + else if (p > len) + return -1; + else + return re_match_2(buf, 0, 0, (char*)s, len, p, reg, len); +} + +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); + diff --git a/gnu/lib/libg++/g++-include/Regex.h b/gnu/lib/libg++/g++-include/Regex.h new file mode 100644 index 00000000000..e7ca449345e --- /dev/null +++ b/gnu/lib/libg++/g++-include/Regex.h @@ -0,0 +1,77 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Regex.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef _Regex_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Regex_h 1 + +#if defined(SHORT_NAMES) || defined(VMS) +#define re_compile_pattern recmppat +#define re_pattern_buffer repatbuf +#define re_registers reregs +#endif + +struct re_pattern_buffer; // defined elsewhere +struct re_registers; + +class Regex +{ +private: + + Regex(const Regex&) {} // no X(X&) + void operator = (const Regex&) {} // no assignment + +protected: + re_pattern_buffer* buf; + re_registers* reg; + +public: + Regex(const char* t, + 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 +}; + +// 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_]*" + + +#endif diff --git a/gnu/lib/libg++/g++-include/RndInt.cc b/gnu/lib/libg++/g++-include/RndInt.cc new file mode 100644 index 00000000000..c09f1e504d3 --- /dev/null +++ b/gnu/lib/libg++/g++-include/RndInt.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <RndInt.h> diff --git a/gnu/lib/libg++/g++-include/RndInt.h b/gnu/lib/libg++/g++-include/RndInt.h new file mode 100644 index 00000000000..40165a5b8e4 --- /dev/null +++ b/gnu/lib/libg++/g++-include/RndInt.h @@ -0,0 +1,177 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1990 Free Software Foundation + adapted from a submission from John Reidl <riedl@cs.purdue.edu> + + +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 +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: RndInt.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef _RandomInteger_h +#ifdef __GNUG__ +#pragma interface +#endif +#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 <math.h> +#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 diff --git a/gnu/lib/libg++/g++-include/SLList.cc b/gnu/lib/libg++/g++-include/SLList.cc new file mode 100644 index 00000000000..725488cab4f --- /dev/null +++ b/gnu/lib/libg++/g++-include/SLList.cc @@ -0,0 +1,247 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _G_NO_TEMPLATES +#ifdef __GNUG__ +//#pragma implementation +#endif +#include <values.h> +#include <stream.h> +#include <builtin.h> +#include "SLList.h" + +void BaseSLList::error(const char* msg) +{ + (*lib_error_handler)("SLList", msg); +} + +int BaseSLList::length() +{ + int l = 0; + BaseSLNode* t = last; + if (t != 0) do { ++l; t = t->tl; } while (t != last); + return l; +} + +void BaseSLList::clear() +{ + if (last == 0) + return; + + BaseSLNode* p = last->tl; + last->tl = 0; + last = 0; + + while (p != 0) + { + BaseSLNode* nxt = p->tl; + delete_node(p); + p = nxt; + } +} + + +// Note: This is an internal method. It does *not* free old contents! + +void BaseSLList::copy(const BaseSLList& a) +{ + if (a.last == 0) + last = 0; + else + { + BaseSLNode* p = a.last->tl; + BaseSLNode* h = copy_node(p->item()); + last = h; + for (;;) + { + if (p == a.last) + { + last->tl = h; + return; + } + p = p->tl; + BaseSLNode* n = copy_node(p->item()); + last->tl = n; + last = n; + } + } +} + +BaseSLList& BaseSLList::operator = (const BaseSLList& a) +{ + if (last != a.last) + { + clear(); + copy(a); + } + return *this; +} + +Pix BaseSLList::prepend(void *datum) +{ + return prepend(copy_node(datum)); +} + + +Pix BaseSLList::prepend(BaseSLNode* 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 BaseSLList::append(void *datum) +{ + return append(copy_node(datum)); +} + +Pix BaseSLList::append(BaseSLNode* 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 BaseSLList::join(BaseSLList& b) +{ + BaseSLNode* t = b.last; + b.last = 0; + if (last == 0) + last = t; + else if (t != 0) + { + BaseSLNode* f = last->tl; + last->tl = t->tl; + t->tl = f; + last = t; + } +} + +Pix BaseSLList::ins_after(Pix p, void *datum) +{ + BaseSLNode* u = (BaseSLNode*)p; + BaseSLNode* t = copy_node(datum); + 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 BaseSLList::del_after(Pix p) +{ + BaseSLNode* u = (BaseSLNode*)p; + if (last == 0 || u == last) error("cannot del_after last"); + if (u == 0) u = last; // del_after 0 means delete first + BaseSLNode* t = u->tl; + if (u == t) + last = 0; + else + { + u->tl = t->tl; + if (last == t) + last = u; + } + delete_node(t); +} + +int BaseSLList::owns(Pix p) +{ + BaseSLNode* t = last; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->tl; + } while (t != last); + } + return 0; +} + +int BaseSLList::remove_front(void *dst, int signal_error) +{ + if (last) + { + BaseSLNode* t = last->tl; + copy_item(dst, t->item()); + if (t == last) + last = 0; + else + last->tl = t->tl; + delete_node(t); + return 1; + } + if (signal_error) + error("remove_front of empty list"); + return 0; +} + +void BaseSLList::del_front() +{ + if (last == 0) error("del_front of empty list"); + BaseSLNode* t = last->tl; + if (t == last) + last = 0; + else + last->tl = t->tl; + delete_node(t); +} + +int BaseSLList::OK() +{ + int v = 1; + if (last != 0) + { + BaseSLNode* 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; +} +#endif /*!_G_NO_TEMPLATES*/ diff --git a/gnu/lib/libg++/g++-include/SLList.h b/gnu/lib/libg++/g++-include/SLList.h new file mode 100644 index 00000000000..499968caf5d --- /dev/null +++ b/gnu/lib/libg++/g++-include/SLList.h @@ -0,0 +1,117 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: SLList.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef _SLList_h +#ifdef __GNUG__ +//#pragma interface +#endif +#define _SLList_h 1 + +#include <Pix.h> + +struct BaseSLNode +{ + BaseSLNode *tl; + void *item() {return (void*)(this+1);} // Return ((SLNode<T>*)this)->hd +}; + +template<class T> +class SLNode : public BaseSLNode +{ + public: + T hd; // Data part of node + SLNode() { } + SLNode(const T& h, SLNode* t = 0) + : hd(h) { tl = t; } + ~SLNode() { } +}; + +extern int __SLListLength(BaseSLNode *ptr); + +class BaseSLList { + protected: + BaseSLNode *last; + virtual void delete_node(BaseSLNode*node) = 0; + virtual BaseSLNode* copy_node(void* datum) = 0; + virtual void copy_item(void *dst, void *src) = 0; + virtual ~BaseSLList() { } + BaseSLList() { last = 0; } + void copy(const BaseSLList&); + BaseSLList& operator = (const BaseSLList& a); + Pix ins_after(Pix p, void *datum); + Pix prepend(void *datum); + Pix append(void *datum); + int remove_front(void *dst, int signal_error = 0); + void join(BaseSLList&); + public: + int length(); + void clear(); + Pix prepend(BaseSLNode*); + Pix append(BaseSLNode*); + int OK(); + void error(const char* msg); + void del_after(Pix p); + int owns(Pix p); + void del_front(); +}; + +template <class T> +class SLList : public BaseSLList +{ + private: + virtual void delete_node(BaseSLNode *node) { delete (SLNode<T>*)node; } + virtual BaseSLNode* copy_node(void *datum) + { return new SLNode<T>(*(T*)datum); } + virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; } + +public: + SLList() : BaseSLList() { } + SLList(const SLList<T>& a) : BaseSLList() { copy(a); } + SLList<T>& operator = (const SLList<T>& a) + { BaseSLList::operator=((const BaseSLList&) a); return *this; } + virtual ~SLList() { clear(); } + + int empty() { return last == 0; } + + Pix prepend(T& item) {return BaseSLList::prepend(&item);} + Pix append(T& item) {return BaseSLList::append(&item);} + Pix prepend(SLNode<T>* node) {return BaseSLList::prepend(node);} + Pix append(SLNode<T>* node) {return BaseSLList::append(node);} + + T& operator () (Pix p) { + if (p == 0) error("null Pix"); + return ((SLNode<T>*)(p))->hd; } + inline Pix first() { return (last == 0)? 0 : Pix(last->tl); } + void next(Pix& p) + { p = (p == 0 || p == last)? 0 : Pix(((SLNode<T>*)(p))->tl); } + Pix ins_after(Pix p, T& item) { return BaseSLList::ins_after(p, &item); } + void join(SLList<T>& a) { BaseSLList::join(a); } + + T& front() { + if (last == 0) error("front: empty list"); + return ((SLNode<T>*)last->tl)->hd; } + T& rear() { + if (last == 0) error("rear: empty list"); + return ((SLNode<T>*)last)->hd; } + int remove_front(T& x) { return BaseSLList::remove_front(&x); } + T remove_front() { T dst; BaseSLList::remove_front(&dst, 1); return dst; } +}; + +#endif diff --git a/gnu/lib/libg++/g++-include/SmplHist.cc b/gnu/lib/libg++/g++-include/SmplHist.cc new file mode 100644 index 00000000000..a1fcd155a87 --- /dev/null +++ b/gnu/lib/libg++/g++-include/SmplHist.cc @@ -0,0 +1,112 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <SmplHist.h> +#include <math.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#include <float.h> +#define HUGE_VAL DBL_MAX +#endif +#endif + +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_VAL; /* 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_VAL) { + 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; + } + } +} + diff --git a/gnu/lib/libg++/g++-include/SmplHist.h b/gnu/lib/libg++/g++-include/SmplHist.h new file mode 100644 index 00000000000..d8efe119d78 --- /dev/null +++ b/gnu/lib/libg++/g++-include/SmplHist.h @@ -0,0 +1,74 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: SmplHist.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef SampleHistogram_h +#ifdef __GNUG__ +#pragma interface +#endif +#define SampleHistogram_h 1 + +#include <iostream.h> +#include <SmplStat.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); + + int buckets(); + + double bucketThreshold(int i); + int inBucket(int i); + void printBuckets(ostream&); + +}; + + +inline int SampleHistogram:: buckets() { return(howManyBuckets); }; + +inline double SampleHistogram:: bucketThreshold(int i) { + if (i < 0 || i >= howManyBuckets) + error("invalid bucket access"); + return(bucketLimit[i]); +} + +inline int SampleHistogram:: inBucket(int i) { + if (i < 0 || i >= howManyBuckets) + error("invalid bucket access"); + return(bucketCount[i]); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/SmplStat.cc b/gnu/lib/libg++/g++-include/SmplStat.cc new file mode 100644 index 00000000000..461bea43aff --- /dev/null +++ b/gnu/lib/libg++/g++-include/SmplStat.cc @@ -0,0 +1,160 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <SmplStat.h> +#include <math.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#include <float.h> +#define HUGE_VAL DBL_MAX +#endif +#endif + +// 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_VAL; + 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_VAL; + minValue = HUGE_VAL; +} + +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) +{ + int df = n - 1; + if (df <= 0) return HUGE_VAL; + double t = tval(double(100 + interval) * 0.005, df); + if (t == HUGE_VAL) + return t; + else + return (t * stdDev()) / sqrt(double(n)); +} + +double +SampleStatistic::confidence(double p_value) +{ + int df = n - 1; + if (df <= 0) return HUGE_VAL; + double t = tval((1.0 + p_value) * 0.5, df); + if (t == HUGE_VAL) + return t; + else + return (t * stdDev()) / sqrt(double(n)); +} + + diff --git a/gnu/lib/libg++/g++-include/SmplStat.h b/gnu/lib/libg++/g++-include/SmplStat.h new file mode 100644 index 00000000000..6b0a8b04e7d --- /dev/null +++ b/gnu/lib/libg++/g++-include/SmplStat.h @@ -0,0 +1,69 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: SmplStat.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef SampleStatistic_h +#ifdef __GNUG__ +#pragma interface +#endif +#define SampleStatistic_h 1 + +#include <builtin.h> + +class SampleStatistic { +protected: + int n; + double x; + double x2; + double minValue, maxValue; + + public : + + SampleStatistic(); + virtual ~SampleStatistic(); + virtual void reset(); + + virtual void operator+=(double); + int samples(); + double mean(); + double stdDev(); + double var(); + double min(); + double max(); + 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); + +inline SampleStatistic:: SampleStatistic(){ reset();} +inline int SampleStatistic:: samples() {return(n);} +inline double SampleStatistic:: min() {return(minValue);} +inline double SampleStatistic:: max() {return(maxValue);} +inline SampleStatistic::~SampleStatistic() {} + +#endif diff --git a/gnu/lib/libg++/g++-include/String.cc b/gnu/lib/libg++/g++-include/String.cc new file mode 100644 index 00000000000..6e7a9f87e6c --- /dev/null +++ b/gnu/lib/libg++/g++-include/String.cc @@ -0,0 +1,1311 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + String class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <String.h> +#include <std.h> +#include <ctype.h> +#include <limits.h> +#include <new.h> +#include <builtin.h> + +// extern "C" { +#include <regex.h> +// } + +void String::error(const char* msg) const +{ + (*lib_error_handler)("String", msg); +} + +String::operator const char*() const +{ + return (const char*)chars(); +} + +// 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; + } + else + to[n] = 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 << (sizeof(short) * CHAR_BIT - 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) ulen = 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; +} + + + +/* + * 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 || (unsigned)(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::operator() (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; +} + + +#if defined(__GNUG__) && !defined(NO_NRV) + +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()); +} + +#else + +String join(String src[], int n, const String& separator) +{ + String 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()); + return x; +} + +#endif + +/* + 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; +} + +#if defined(__GNUG__) && !defined(NO_NRV) + +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); +} + +#else + +String replicate(char c, int n) +{ + String w; + w.rep = Sresize(w.rep, n); + char* p = w.rep->s; + while (n-- > 0) *p++ = c; + *p = 0; + return w; +} + +String replicate(const String& y, int n) +{ + String 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; + return w; +} + +String common_prefix(const String& x, const String& y, int startpos) +{ + String 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); + return r; +} + +String common_suffix(const String& x, const String& y, int startpos) +{ + String 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); + return r; +} + +#endif + +// IO + +istream& operator>>(istream& s, String& x) +{ + if (!s.ipfx(0) || (!(s.flags() & ios::skipws) && !ws(s))) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } + int ch; + int i = 0; + x.rep = Sresize(x.rep, 20); + register streambuf *sb = s.rdbuf(); + while ((ch = sb->sbumpc()) != EOF) + { + 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; + int new_state = s.rdstate(); + if (i == 0) new_state |= ios::failbit; + if (ch == EOF) new_state |= ios::eofbit; + s.clear(new_state); + return s; +} + +int readline(istream& s, String& x, char terminator, int discard) +{ + if (!s.ipfx(0)) + return 0; + int ch; + int i = 0; + x.rep = Sresize(x.rep, 80); + register streambuf *sb = s.rdbuf(); + while ((ch = sb->sbumpc()) != EOF) + { + 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; + if (ch == EOF) s.clear(ios::eofbit|s.rdstate()); + 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 (unsigned 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 (unsigned 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 (unsigned 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 (unsigned int i = 0; i < length(); i++) + if (match(i,length(),0,&c,1) >= 0) found++; + return(found); +} + + +int String::OK() const +{ + if (rep == 0 // don't have a rep + || rep->len > rep->sz // string oustide bounds + || rep->s[rep->len] != 0) // not null-terminated + error("invariant failure"); + return 1; +} + +int SubString::OK() const +{ + int v = S != (const char*)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; +} + diff --git a/gnu/lib/libg++/g++-include/String.h b/gnu/lib/libg++/g++-include/String.h new file mode 100644 index 00000000000..0a6ad822039 --- /dev/null +++ b/gnu/lib/libg++/g++-include/String.h @@ -0,0 +1,1318 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: String.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + + +#ifndef _String_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _String_h 1 + +#include <iostream.h> +#include <Regex.h> + +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 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 + + unsigned int length() const; + int empty() const; + const char* chars() const; + + int OK() const; + +}; + + +class String +{ + friend class SubString; + +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); + + +// 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 operator () (int pos, int len); // synonym for at + + 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 + + unsigned int length() const; + int empty() const; + +// preallocate some space for String + void alloc(int newsize); + +// report current allocation (not length!) + + int allocation() const; + + + 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 + +extern StrRep _nilStrRep; +extern String _nilString; + +// other inlines + +String operator + (const String& x, const String& y); +String operator + (const String& x, const SubString& y); +String operator + (const String& x, const char* y); +String operator + (const String& x, char y); +String operator + (const SubString& x, const String& y); +String operator + (const SubString& x, const SubString& y); +String operator + (const SubString& x, const char* y); +String operator + (const SubString& x, char y); +String operator + (const char* x, const String& y); +String operator + (const char* x, const SubString& y); + +int operator==(const String& x, const String& y); +int operator!=(const String& x, const String& y); +int operator> (const String& x, const String& y); +int operator>=(const String& x, const String& y); +int operator< (const String& x, const String& y); +int operator<=(const String& x, const String& y); +int operator==(const String& x, const SubString& y); +int operator!=(const String& x, const SubString& y); +int operator> (const String& x, const SubString& y); +int operator>=(const String& x, const SubString& y); +int operator< (const String& x, const SubString& y); +int operator<=(const String& x, const SubString& y); +int operator==(const String& x, const char* t); +int operator!=(const String& x, const char* t); +int operator> (const String& x, const char* t); +int operator>=(const String& x, const char* t); +int operator< (const String& x, const char* t); +int operator<=(const String& x, const char* t); +int operator==(const SubString& x, const String& y); +int operator!=(const SubString& x, const String& y); +int operator> (const SubString& x, const String& y); +int operator>=(const SubString& x, const String& y); +int operator< (const SubString& x, const String& y); +int operator<=(const SubString& x, const String& y); +int operator==(const SubString& x, const SubString& y); +int operator!=(const SubString& x, const SubString& y); +int operator> (const SubString& x, const SubString& y); +int operator>=(const SubString& x, const SubString& y); +int operator< (const SubString& x, const SubString& y); +int operator<=(const SubString& x, const SubString& y); +int operator==(const SubString& x, const char* t); +int operator!=(const SubString& x, const char* t); +int operator> (const SubString& x, const char* t); +int operator>=(const SubString& x, const char* t); +int operator< (const SubString& x, const char* t); +int operator<=(const SubString& x, const char* t); + + +// status reports, needed before defining other things + +inline unsigned 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 unsigned 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 + +#if defined(__GNUG__) && !defined(NO_NRV) + +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); +} + +inline String reverse(const String& x) return r; +{ + r.rep = Sreverse(x.rep, r.rep); +} + +inline String upcase(const String& x) return r; +{ + r.rep = Supcase(x.rep, r.rep); +} + +inline String downcase(const String& x) return r; +{ + r.rep = Sdowncase(x.rep, r.rep); +} + +inline String capitalize(const String& x) return r; +{ + r.rep = Scapitalize(x.rep, r.rep); +} + +#else /* NO_NRV */ + +inline String operator + (const String& x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, const char* y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, char y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const char* y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, char y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const char* x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const char* x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String reverse(const String& x) +{ + String r; r.rep = Sreverse(x.rep, r.rep); return r; +} + +inline String upcase(const String& x) +{ + String r; r.rep = Supcase(x.rep, r.rep); return r; +} + +inline String downcase(const String& x) +{ + String r; r.rep = Sdowncase(x.rep, r.rep); return r; +} + +inline String capitalize(const String& x) +{ + String r; r.rep = Scapitalize(x.rep, r.rep); return r; +} + +#endif + +// 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 void String::reverse() +{ + rep = Sreverse(rep, rep); +} + + +inline void String::upcase() +{ + rep = Supcase(rep, rep); +} + + +inline void String::downcase() +{ + rep = Sdowncase(rep, 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, 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 ostream& operator<<(ostream& s, const String& x) +{ + s << 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; +} + + +// 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 diff --git a/gnu/lib/libg++/g++-include/Uniform.cc b/gnu/lib/libg++/g++-include/Uniform.cc new file mode 100644 index 00000000000..2bf7259bdca --- /dev/null +++ b/gnu/lib/libg++/g++-include/Uniform.cc @@ -0,0 +1,27 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Uniform.h> + +double Uniform::operator()() +{ + return( pLow + delta * pGenerator -> asDouble() ); +} diff --git a/gnu/lib/libg++/g++-include/Uniform.h b/gnu/lib/libg++/g++-include/Uniform.h new file mode 100644 index 00000000000..1f3318303d9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Uniform.h @@ -0,0 +1,74 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Uniform.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +#ifndef _Uniform_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Uniform_h 1 + +#include <Random.h> + +// +// 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()(); +}; + + +inline Uniform::Uniform(double low, double high, RNG *gen) : Random(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 diff --git a/gnu/lib/libg++/g++-include/Weibull.cc b/gnu/lib/libg++/g++-include/Weibull.cc new file mode 100644 index 00000000000..02670b933d2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/Weibull.cc @@ -0,0 +1,33 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <Random.h> +#include <Weibull.h> + +// +// See Simulation, Modelling & Analysis by Law & Kelton, pp259 +// +// This is the ``polar'' method. +// + +double Weibull::operator()() +{ + return( pow(pBeta * ( - log(1 - pGenerator -> asDouble()) ), pInvAlpha) ); +} diff --git a/gnu/lib/libg++/g++-include/Weibull.h b/gnu/lib/libg++/g++-include/Weibull.h new file mode 100644 index 00000000000..9e09ee00f8f --- /dev/null +++ b/gnu/lib/libg++/g++-include/Weibull.h @@ -0,0 +1,76 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: Weibull.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ +#ifndef _Weibull_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Weibull_h + +#include <Random.h> + +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()(); +}; + + +inline void Weibull::setState() { + pInvAlpha = 1.0 / pAlpha; +} + +inline Weibull::Weibull(double alpha, double beta, RNG *gen) : Random(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 diff --git a/gnu/lib/libg++/g++-include/_G_config.h b/gnu/lib/libg++/g++-include/_G_config.h new file mode 100644 index 00000000000..109a3d622a5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/_G_config.h @@ -0,0 +1,52 @@ +/* $Id: _G_config.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ */ + +/* AUTOMATICALLY GENERATED; DO NOT EDIT! */ +#ifndef _G_config_h +#define _G_config_h +#define _G_LIB_VERSION "2.4" +#define _G_NAMES_HAVE_UNDERSCORE 1 +#define _G_DOLLAR_IN_LABEL 1 +#define _G_HAVE_ST_BLKSIZE 1 +typedef unsigned long _G_clock_t; +typedef short _G_dev_t; +typedef long _G_fpos_t; +typedef unsigned short _G_gid_t; +typedef unsigned long _G_ino_t; +typedef unsigned short _G_mode_t; +typedef unsigned short _G_nlink_t; +typedef long _G_off_t; +typedef short _G_pid_t; +typedef int _G_ptrdiff_t; +typedef unsigned int _G_sigset_t; +typedef unsigned int _G_size_t; +typedef long _G_time_t; +typedef unsigned short _G_uid_t; +typedef unsigned short _G_wchar_t; +typedef int /* default */ _G_int32_t; +typedef unsigned int /* default */ _G_uint32_t; +typedef int /* default */ _G_ssize_t; +typedef char* /* default */ _G_va_list; +#define _G_signal_return_type void +#define _G_sprintf_return_type int +#define _G_BUFSIZ 1024 +#define _G_FOPEN_MAX 20 +#define _G_FILENAME_MAX 1024 +#define _G_NULL 0 /* default */ +#define _G_USE_PROTOS +#ifdef _G_USE_PROTOS +#define _G_ARGS(ARGLIST) ARGLIST +#else +#define _G_ARGS(ARGLIST) (...) +#endif +/* #define _G_SYSV */ +#define _G_HAVE_SYS_RESOURCE 1 +#define _G_HAVE_SYS_SOCKET 1 +#define _G_HAVE_SYS_WAIT 1 +#define _G_HAVE_UNISTD 1 +#define _G_HAVE_DIRENT 1 +#define _G_HAVE_CURSES 1 +#define _G_CURSES_FORMAT_ARG const char *fmt, +#define _G_MATH_H_INLINES 0 +/* #define _G_BROKEN_SIGNED_CHAR */ +/* #define _G_FRIEND_BUG */ +#endif /* !_G_config_h */ diff --git a/gnu/lib/libg++/g++-include/builtin.cc b/gnu/lib/libg++/g++-include/builtin.cc new file mode 100644 index 00000000000..6b9abe5380c --- /dev/null +++ b/gnu/lib/libg++/g++-include/builtin.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> diff --git a/gnu/lib/libg++/g++-include/builtin.h b/gnu/lib/libg++/g++-include/builtin.h new file mode 100644 index 00000000000..0c52258eaee --- /dev/null +++ b/gnu/lib/libg++/g++-include/builtin.h @@ -0,0 +1,160 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: builtin.h,v 1.1 1995/10/18 08:38:18 deraadt Exp $ +*/ + +/* + arithmetic, etc. functions on built in types +*/ + + +#ifndef _builtin_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _builtin_h 1 + +#include <stddef.h> +#include <std.h> +#include <math.h> + +#ifdef __GNUG__ +#define _VOLATILE_VOID volatile void +#else +#define _VOLATILE_VOID void +#endif + +typedef void (*one_arg_error_handler_t)(const char*); +typedef void (*two_arg_error_handler_t)(const char*, const char*); + +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* dtoa(double x, char cvt = 'g', int width = 0, int prec = 6); + +unsigned int hashpjw(const char*); +unsigned int multiplicativehash(int); +unsigned int foldhash(double); + +extern _VOLATILE_VOID default_one_arg_error_handler(const char*); +extern _VOLATILE_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); + + +double abs(double arg); +float abs(float arg); +short abs(short arg); +long abs(long arg); +int sign(long arg); +int sign(double arg); +long sqr(long arg); +double sqr(double arg); +int even(long arg); +int odd(long arg); +long lcm(long x, long y); +void (setbit)(long& x, long b); +void clearbit(long& x, long b); +int testbit(long x, long b); + +#if !defined(IV) + +#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */ +inline double abs(double arg) +{ + return (arg < 0.0)? -arg : arg; +} +#endif + +inline float abs(float arg) +{ + return (arg < 0.0)? -arg : arg; +} + +inline short abs(short arg) +{ + return (arg < 0)? -arg : arg; +} + +inline long abs(long arg) +{ + return (arg < 0)? -arg : arg; +} + +inline int sign(long arg) +{ + return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 ); +} + +inline int sign(double arg) +{ + return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 ); +} + +inline long sqr(long arg) +{ + return arg * arg; +} + +#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */ +inline double sqr(double arg) +{ + return arg * arg; +} +#endif + +inline int even(long arg) +{ + return !(arg & 1); +} + +inline int odd(long arg) +{ + return (arg & 1); +} + +inline long lcm(long x, long y) +{ + return x / gcd(x, y) * y; +} + +inline void (setbit)(long& x, long b) +{ + x |= (1 << b); +} + +inline void clearbit(long& x, long b) +{ + x &= ~(1 << b); +} + +inline int testbit(long x, long b) +{ + return ((x & (1 << b)) != 0); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/chr.cc b/gnu/lib/libg++/g++-include/chr.cc new file mode 100644 index 00000000000..d580a629f5a --- /dev/null +++ b/gnu/lib/libg++/g++-include/chr.cc @@ -0,0 +1,37 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <AllocRing.h> + +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; +} diff --git a/gnu/lib/libg++/g++-include/compare.cc b/gnu/lib/libg++/g++-include/compare.cc new file mode 100644 index 00000000000..aae8409a2aa --- /dev/null +++ b/gnu/lib/libg++/g++-include/compare.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <compare.h> diff --git a/gnu/lib/libg++/g++-include/compare.h b/gnu/lib/libg++/g++-include/compare.h new file mode 100644 index 00000000000..a4730244881 --- /dev/null +++ b/gnu/lib/libg++/g++-include/compare.h @@ -0,0 +1,92 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: compare.h,v 1.1 1995/10/18 08:38:19 deraadt Exp $ +*/ + +#ifndef _compare_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _compare_h 1 + +#include <builtin.h> + +int compare(int a, int b); +int compare(short a, short b); +int compare(unsigned long a, unsigned long b); +int compare(unsigned int a, unsigned int b); +int compare(unsigned short a, unsigned short b); +int compare(unsigned char a, unsigned char b); +int compare(signed char a, signed char b); +int compare(float a, float b); +int compare(double a, double b); +int compare(const char* a, const char* b); + + +inline int compare(int a, int b) +{ + return a - b; +} + +inline int compare(short a, short b) +{ + return a - b; +} + + +inline int compare(signed char a, signed 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)? -1 : (a > b)? 1 : 0; +} + +inline int compare(double a, double b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(const char* a, const char* b) +{ + return strcmp(a,b); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/dtoa.cc b/gnu/lib/libg++/g++-include/dtoa.cc new file mode 100644 index 00000000000..81d7551daae --- /dev/null +++ b/gnu/lib/libg++/g++-include/dtoa.cc @@ -0,0 +1,335 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <math.h> +#include <values.h> +#include <AllocRing.h> + +extern AllocRing _libgxx_fmtq; + +#ifdef __GNUC__ /* cfront cannot compile this routine */ +// OBSOLETE ROUTINE! + +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 / M_LN10) * 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; + } + double almost_one = 1.0 - rounder; + while (fpnum > 0.0 && fpnum < almost_one) + { + 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; +} +#endif diff --git a/gnu/lib/libg++/g++-include/error.cc b/gnu/lib/libg++/g++-include/error.cc new file mode 100644 index 00000000000..fc14959c4da --- /dev/null +++ b/gnu/lib/libg++/g++-include/error.cc @@ -0,0 +1,51 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> + +extern "C" _VOLATILE_VOID abort(); + +_VOLATILE_VOID default_one_arg_error_handler(const char* msg) +{ + fputs("Error: ", stderr); + fputs(msg, stderr); + fputs("\n", stderr); + abort(); +} + + +_VOLATILE_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; +} + diff --git a/gnu/lib/libg++/g++-include/fmtq.cc b/gnu/lib/libg++/g++-include/fmtq.cc new file mode 100644 index 00000000000..7a9dd7b4f3c --- /dev/null +++ b/gnu/lib/libg++/g++-include/fmtq.cc @@ -0,0 +1,29 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <AllocRing.h> + +// 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); diff --git a/gnu/lib/libg++/g++-include/gcd.cc b/gnu/lib/libg++/g++-include/gcd.cc new file mode 100644 index 00000000000..76ff0ef1b8e --- /dev/null +++ b/gnu/lib/libg++/g++-include/gcd.cc @@ -0,0 +1,52 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> + + +/* + 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; + } + } +} diff --git a/gnu/lib/libg++/g++-include/gen/AVLMap.ccP b/gnu/lib/libg++/g++-include/gen/AVLMap.ccP new file mode 100644 index 00000000000..12b52f5e92a --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVLMap.ccP @@ -0,0 +1,608 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.<C>.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(<T><C>AVLNode* t) +{ + return t->stat & AVLBALANCEMASK; +} + +static inline void set_bf(<T><C>AVLNode* t, int b) +{ + t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); +} + + +static inline int rthread(<T><C>AVLNode* t) +{ + return t->stat & RTHREADBIT; +} + +static inline void set_rthread(<T><C>AVLNode* t, int b) +{ + if (b) + t->stat |= RTHREADBIT; + else + t->stat &= ~RTHREADBIT; +} + +static inline int lthread(<T><C>AVLNode* t) +{ + return t->stat & LTHREADBIT; +} + +static inline void set_lthread(<T><C>AVLNode* t, int b) +{ + if (b) + t->stat |= LTHREADBIT; + else + t->stat &= ~LTHREADBIT; +} + +/* + traversal primitives +*/ + + +<T><C>AVLNode* <T><C>AVLMap::leftmost() +{ + <T><C>AVLNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T><C>AVLNode* <T><C>AVLMap::rightmost() +{ + <T><C>AVLNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T><C>AVLNode* <T><C>AVLMap::succ(<T><C>AVLNode* t) +{ + <T><C>AVLNode* r = t->rt; + if (!rthread(t)) while (!lthread(r)) r = r->lt; + return r; +} + +<T><C>AVLNode* <T><C>AVLMap::pred(<T><C>AVLNode* t) +{ + <T><C>AVLNode* l = t->lt; + if (!lthread(t)) while (!rthread(l)) l = l->rt; + return l; +} + + +Pix <T><C>AVLMap::seek(<T&> key) +{ + <T><C>AVLNode* t = root; + if (t == 0) + return 0; + for (;;) + { + int cmp = <T>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 <T>* _target_item; // add/del_item target +static <T><C>AVLNode* _found_node; // returned added/deleted node +static int _already_found; // for deletion subcases + + +void <T><C>AVLMap:: _add(<T><C>AVLNode*& t) +{ + int cmp = <T>CMP(*_target_item, t->item); + if (cmp == 0) + { + _found_node = t; + return; + } + else if (cmp < 0) + { + if (lthread(t)) + { + ++count; + _found_node = new <T><C>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: + <T><C>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 + { + <T><C>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 <T><C>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: + <T><C>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 + { + <T><C>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; + } + } + } + } +} + + +<C>& <T><C>AVLMap::operator [] (<T&> item) +{ + if (root == 0) + { + ++count; + root = new <T><C>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 <T><C>AVLMap::_del(<T><C>AVLNode* par, <T><C>AVLNode*& t) +{ + int comp; + if (_already_found) + { + if (rthread(t)) + comp = 0; + else + comp = 1; + } + else + comp = <T>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; + <T><C>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; + <T><C>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 + { + <T><C>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: + <T><C>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: + <T><C>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: + <T><C>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: + <T><C>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 <T><C>AVLMap::del(<T&> 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 <T><C>AVLMap::_kill(<T><C>AVLNode* t) +{ + if (t != 0) + { + if (!lthread(t)) _kill(t->lt); + if (!rthread(t)) _kill(t->rt); + delete t; + } +} + + +<T><C>AVLMap::<T><C>AVLMap(<T><C>AVLMap& b) :<T><C>Map(b.def) +{ + root = 0; + count = 0; + for (Pix i = b.first(); i != 0; b.next(i)) + (*this)[b.key(i)] = b.contents(i); +} + + +int <T><C>AVLMap::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T><C>AVLNode* trail = leftmost(); + <T><C>AVLNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/AVLMap.hP b/gnu/lib/libg++/g++-include/gen/AVLMap.hP new file mode 100644 index 00000000000..cbf0ffbe7bc --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVLMap.hP @@ -0,0 +1,157 @@ +// 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 _<T><C>AVLMap_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>AVLMap_h 1 + +#include "<T>.<C>.Map.h" + +struct <T><C>AVLNode +{ + <T><C>AVLNode* lt; + <T><C>AVLNode* rt; + <T> item; + <C> cont; + char stat; + <T><C>AVLNode(<T&> h, <C&> c, + <T><C>AVLNode* l=0, <T><C>AVLNode* r=0); + ~<T><C>AVLNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>AVLNode::<T><C>AVLNode(<T&> h, <C&> c, + <T><C>AVLNode* l, <T><C>AVLNode* r) + :item(h), cont(c), lt(l), rt(r), stat(0) {} + +inline <T><C>AVLNode::~<T><C>AVLNode() {} + +#endif + +typedef <T><C>AVLNode* <T><C>AVLNodePtr; + + +class <T><C>AVLMap : public <T><C>Map +{ +protected: + <T><C>AVLNode* root; + + <T><C>AVLNode* leftmost(); + <T><C>AVLNode* rightmost(); + <T><C>AVLNode* pred(<T><C>AVLNode* t); + <T><C>AVLNode* succ(<T><C>AVLNode* t); + void _kill(<T><C>AVLNode* t); + void _add(<T><C>AVLNode*& t); + void _del(<T><C>AVLNode* p, <T><C>AVLNode*& t); + +public: + <T><C>AVLMap(<C&> dflt); + <T><C>AVLMap(<T><C>AVLMap& a); + ~<T><C>AVLMap(); + + <C>& operator [] (<T&> key); + + void del(<T&> key); + + Pix first(); + void next(Pix& i); + <T>& key(Pix i); + <C>& contents(Pix i); + + Pix seek(<T&> key); + int contains(<T&> key); + + void clear(); + + Pix last(); + void prev(Pix& i); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>AVLMap::~<T><C>AVLMap() +{ + _kill(root); +} + +inline <T><C>AVLMap::<T><C>AVLMap(<C&> dflt) :(dflt) +{ + root = 0; +} + + +inline Pix <T><C>AVLMap::first() +{ + return Pix(leftmost()); +} + +inline Pix <T><C>AVLMap::last() +{ + return Pix(rightmost()); +} + +inline void <T><C>AVLMap::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T><C>AVLNode*)i)); +} + +inline void <T><C>AVLMap::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T><C>AVLNode*)i)); +} + +inline <T>& <T><C>AVLMap::key(Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>AVLNode*)i)->item; +} + +inline <C>& <T><C>AVLMap::contents(Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>AVLNode*)i)->cont; +} + +inline void <T><C>AVLMap::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T><C>AVLMap::contains(<T&> key) +{ + return seek(key) != 0; +} + + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/AVLSet.ccP b/gnu/lib/libg++/g++-include/gen/AVLSet.ccP new file mode 100644 index 00000000000..ee433257c09 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVLSet.ccP @@ -0,0 +1,885 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.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(<T>AVLNode* t) +{ + return t->stat & AVLBALANCEMASK; +} + +static inline void set_bf(<T>AVLNode* t, int b) +{ + t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); +} + + +static inline int rthread(<T>AVLNode* t) +{ + return t->stat & RTHREADBIT; +} + +static inline void set_rthread(<T>AVLNode* t, int b) +{ + if (b) + t->stat |= RTHREADBIT; + else + t->stat &= ~RTHREADBIT; +} + +static inline int lthread(<T>AVLNode* t) +{ + return t->stat & LTHREADBIT; +} + +static inline void set_lthread(<T>AVLNode* t, int b) +{ + if (b) + t->stat |= LTHREADBIT; + else + t->stat &= ~LTHREADBIT; +} + +/* + traversal primitives +*/ + + +<T>AVLNode* <T>AVLSet::leftmost() +{ + <T>AVLNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T>AVLNode* <T>AVLSet::rightmost() +{ + <T>AVLNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T>AVLNode* <T>AVLSet::succ(<T>AVLNode* t) +{ + <T>AVLNode* r = t->rt; + if (!rthread(t)) while (!lthread(r)) r = r->lt; + return r; +} + +<T>AVLNode* <T>AVLSet::pred(<T>AVLNode* t) +{ + <T>AVLNode* l = t->lt; + if (!lthread(t)) while (!rthread(l)) l = l->rt; + return l; +} + + +Pix <T>AVLSet::seek(<T&> key) +{ + <T>AVLNode* t = root; + if (t == 0) + return 0; + for (;;) + { + int cmp = <T>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 <T>* _target_item; // add/del_item target +static <T>AVLNode* _found_node; // returned added/deleted node +static int _already_found; // for deletion subcases + +static <T>AVLNode** _hold_nodes; // used for rebuilding trees +static int _max_hold_index; // # elements-1 in _hold_nodes + + +void <T>AVLSet:: _add(<T>AVLNode*& t) +{ + int cmp = <T>CMP(*_target_item, t->item); + if (cmp == 0) + { + _found_node = t; + return; + } + else if (cmp < 0) + { + if (lthread(t)) + { + ++count; + _found_node = new <T>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: + <T>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 + { + <T>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 <T>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: + <T>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 + { + <T>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 <T>AVLSet::add(<T&> item) +{ + if (root == 0) + { + ++count; + root = new <T>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 <T>AVLSet::_del(<T>AVLNode* par, <T>AVLNode*& t) +{ + int comp; + if (_already_found) + { + if (rthread(t)) + comp = 0; + else + comp = 1; + } + else + comp = <T>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; + <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; + <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 + { + <T>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: + <T>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: + <T>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: + <T>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: + <T>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 <T>AVLSet::del(<T&> 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 <T>AVLNode* _do_treeify(int lo, int hi, int& h) +{ + int lh, rh; + int mid = (lo + hi) / 2; + <T>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 <T>AVLNode* _treeify(int n) +{ + <T>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 <T>AVLSet::_kill(<T>AVLNode* t) +{ + if (t != 0) + { + if (!lthread(t)) _kill(t->lt); + if (!rthread(t)) _kill(t->rt); + delete t; + } +} + + +<T>AVLSet::<T>AVLSet(<T>AVLSet& b) +{ + if ((count = b.count) == 0) + { + root = 0; + } + else + { + _hold_nodes = new <T>AVLNodePtr [count]; + <T>AVLNode* t = b.leftmost(); + int i = 0; + while (t != 0) + { + _hold_nodes[i++] = new <T>AVLNode(t->item); + t = b.succ(t); + } + root = _treeify(count); + } +} + + +int <T>AVLSet::operator == (<T>AVLSet& y) +{ + if (count != y.count) + return 0; + else + { + <T>AVLNode* t = leftmost(); + <T>AVLNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (!(<T>EQ(t->item, u->item))) + return 0; + else + { + t = succ(t); + u = y.succ(u); + } + } + } +} + +int <T>AVLSet::operator <= (<T>AVLSet& y) +{ + if (count > y.count) + return 0; + else + { + <T>AVLNode* t = leftmost(); + <T>AVLNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (u == 0) + return 0; + int cmp = <T>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 <T>AVLSet::operator |=(<T>AVLSet& y) +{ + <T>AVLNode* t = leftmost(); + <T>AVLNode* u = y.leftmost(); + int rsize = count + y.count; + _hold_nodes = new <T>AVLNodePtr [rsize]; + int k = 0; + for (;;) + { + if (t == 0) + { + while (u != 0) + { + _hold_nodes[k++] = new <T>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 = <T>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 <T>AVLNode(u->item); + u = y.succ(u); + } + } + root = _treeify(k); + count = k; +} + +void <T>AVLSet::operator &= (<T>AVLSet& y) +{ + <T>AVLNode* t = leftmost(); + <T>AVLNode* u = y.leftmost(); + int rsize = (count < y.count)? count : y.count; + _hold_nodes = new <T>AVLNodePtr [rsize]; + int k = 0; + for (;;) + { + if (t == 0) + break; + if (u == 0) + { + while (t != 0) + { + <T>AVLNode* tmp = succ(t); + delete t; + t = tmp; + } + break; + } + int cmp = <T>CMP(t->item, u->item); + if (cmp == 0) + { + _hold_nodes[k++] = t; + t = succ(t); + u = y.succ(u); + } + else if (cmp < 0) + { + <T>AVLNode* tmp = succ(t); + delete t; + t = tmp; + } + else + u = y.succ(u); + } + root = _treeify(k); + count = k; +} + + +void <T>AVLSet::operator -=(<T>AVLSet& y) +{ + <T>AVLNode* t = leftmost(); + <T>AVLNode* u = y.leftmost(); + int rsize = count; + _hold_nodes = new <T>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 = <T>CMP(t->item, u->item); + if (cmp == 0) + { + <T>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 <T>AVLSet::owns(Pix i) +{ + if (i == 0) return 0; + for (<T>AVLNode* t = leftmost(); t != 0; t = succ(t)) + if (Pix(t) == i) return 1; + return 0; +} + +int <T>AVLSet::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T>AVLNode* trail = leftmost(); + <T>AVLNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/AVLSet.hP b/gnu/lib/libg++/g++-include/gen/AVLSet.hP new file mode 100644 index 00000000000..b9adfb4e748 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVLSet.hP @@ -0,0 +1,167 @@ +// 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 _<T>AVL_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>AVL_h 1 + +#include "<T>.Set.h" + +struct <T>AVLNode +{ + <T>AVLNode* lt; + <T>AVLNode* rt; + <T> item; + char stat; + <T>AVLNode(<T&> h, <T>AVLNode* l=0, <T>AVLNode* r=0); + ~<T>AVLNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>AVLNode::<T>AVLNode(<T&> h, <T>AVLNode* l, <T>AVLNode* r) +:item(h), lt(l), rt(r), stat(0) {} + +inline <T>AVLNode::~<T>AVLNode() {} + +#endif + +typedef <T>AVLNode* <T>AVLNodePtr; + + +class <T>AVLSet : public <T>Set +{ +protected: + <T>AVLNode* root; + + <T>AVLSet(<T>AVLNode* p, int l); + + <T>AVLNode* leftmost(); + <T>AVLNode* rightmost(); + <T>AVLNode* pred(<T>AVLNode* t); + <T>AVLNode* succ(<T>AVLNode* t); + void _kill(<T>AVLNode* t); + void _add(<T>AVLNode*& t); + void _del(<T>AVLNode* p, <T>AVLNode*& t); + +public: + <T>AVLSet(); + <T>AVLSet(<T>AVLSet& a); + ~<T>AVLSet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + Pix last(); + void prev(Pix& i); + + void operator |= (<T>AVLSet& b); + void operator -= (<T>AVLSet& b); + void operator &= (<T>AVLSet& b); + + int operator == (<T>AVLSet& b); + int operator != (<T>AVLSet& b); + int operator <= (<T>AVLSet& b); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>AVLSet::~<T>AVLSet() +{ + _kill(root); +} + +inline <T>AVLSet::<T>AVLSet() +{ + root = 0; + count = 0; +} + +inline <T>AVLSet::<T>AVLSet(<T>AVLNode* p, int l) +{ + root = p; + count = l; +} + +inline int <T>AVLSet::operator != (<T>AVLSet& b) +{ + return ! ((*this) == b); +} + +inline Pix <T>AVLSet::first() +{ + return Pix(leftmost()); +} + +inline Pix <T>AVLSet::last() +{ + return Pix(rightmost()); +} + +inline void <T>AVLSet::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T>AVLNode*)i)); +} + +inline void <T>AVLSet::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T>AVLNode*)i)); +} + +inline <T>& <T>AVLSet::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>AVLNode*)i)->item; +} + +inline void <T>AVLSet::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T>AVLSet::contains(<T&> key) +{ + return seek(key) != 0; +} + + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/AVec.ccP b/gnu/lib/libg++/g++-include/gen/AVec.ccP new file mode 100644 index 00000000000..e2f40345582 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVec.ccP @@ -0,0 +1,401 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.AVec.h" + +/* + The following brought to you by the department of redundancy department +*/ + +<T>AVec& <T>AVec::operator = (<T>AVec& v) +{ + if (len != 0 && len != v.capacity()) + error("nonconformant vectors."); + if (len == 0) + s = new <T> [len = v.capacity()]; + if (s != v.vec()) + { + for (int i = 0; i < len; ++i) + s[i] = v.vec()[i]; + } + return *this; +} + +<T>AVec& <T>AVec::operator = (<T&> f) +{ + for (int i = 0; i < len; ++i) s[i] = f; + return *this; +} + + +<T>AVec concat(<T>AVec & a, <T>AVec & b) +{ + int newl = a.capacity() + b.capacity(); + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while (t < top) *p++ = *t++; + top = &(b.vec()[b.capacity()]); + t = b.vec(); + while (t < top) *p++ = *t++; + return <T>AVec(newl, news); +} + + +<T>AVec combine(<T>Combiner f, <T>AVec& a, <T>AVec& b) +{ + int newl = (a.capacity() < b.capacity())? a.capacity() : b.capacity(); + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* top = &(a.vec()[newl]); + <T>* t = a.vec(); + <T>* u = b.vec(); + while (t < top) *p++ = (*f)(*t++, *u++); + return <T>AVec(newl, news); +} + +<T>AVec reverse(<T>AVec& a) +{ + <T>* news = new <T> [a.capacity()]; + if (a.capacity() != 0) + { + <T>* lo = news; + <T>* hi = &(news[a.capacity() - 1]); + while (lo < hi) + { + <T> tmp = *lo; + *lo++ = *hi; + *hi-- = tmp; + } + } + return <T>AVec(a.capacity(), news); +} + +<T>AVec map(<T>Mapper f, <T>AVec& a) +{ + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while(t < top) *p++ = (*f)(*t++); + return <T>AVec(a.capacity(), news); +} + +<T>AVec <T>AVec::at(int from, int n) +{ + int to; + if (n < 0) + { + n = len - from; + to = len - 1; + } + else + to = from + n - 1; + if ((unsigned)from > to) + range_error(); + <T>* news = new <T> [n]; + <T>* p = news; + <T>* t = &(s[from]); + <T>* top = &(s[to]); + while (t <= top) *p++ = *t++; + return <T>AVec(n, news); +} + +<T>AVec merge(<T>AVec & a, <T>AVec & b, <T>Comparator f) +{ + int newl = a.capacity() + b.capacity(); + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* topa = &(a.vec()[a.capacity()]); + <T>* as = a.vec(); + <T>* topb = &(b.vec()[b.capacity()]); + <T>* 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 <T>AVec(newl, news); +} + +<T>AVec operator + (<T>AVec& a, <T>AVec& b) +{ + a.check_len(b.capacity()); + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + <T>* u = b.vec(); + while (t < top) *p++ = *t++ + *u++; + return <T>AVec(a.capacity(), news); +} + +<T>AVec operator - (<T>AVec& a, <T>AVec& b) +{ + a.check_len(b.capacity()); + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + <T>* u = b.vec(); + while (t < top) *p++ = *t++ - *u++; + return <T>AVec(a.capacity(), news); +} + +<T>AVec product (<T>AVec& a, <T>AVec& b) +{ + a.check_len(b.capacity()); + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + <T>* u = b.vec(); + while (t < top) *p++ = *t++ * *u++; + return <T>AVec(a.capacity(), news); +} + +<T>AVec quotient(<T>AVec& a, <T>AVec& b) +{ + a.check_len(b.capacity()); + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + <T>* u = b.vec(); + while (t < top) *p++ = *t++ / *u++; + return <T>AVec(a.capacity(), news); +} + +<T>AVec operator + (<T>AVec& a, <T&> b) +{ + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while (t < top) *p++ = *t++ + b; + return <T>AVec(a.capacity(), news); +} + +<T>AVec operator - (<T>AVec& a, <T&> b) +{ + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while (t < top) *p++ = *t++ - b; + return <T>AVec(a.capacity(), news); +} + +<T>AVec operator * (<T>AVec& a, <T&> b) +{ + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while (t < top) *p++ = *t++ * b; + return <T>AVec(a.capacity(), news); +} + +<T>AVec operator / (<T>AVec& a, <T&> b) +{ + <T>* news = new <T> [a.capacity()]; + <T>* p = news; + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + while (t < top) *p++ = *t++ / b; + return <T>AVec(a.capacity(), news); +} + +<T>AVec <T>AVec::operator - () +{ + <T>* news = new <T> [len]; + <T>* p = news; + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *p++ = -(*t++); + return <T>AVec(len, news); +} + +<T>AVec& <T>AVec::operator += (<T>AVec& b) +{ + check_len(b.capacity()); + <T>* u = b.vec(); + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ += *u++; + return *this; +} + +<T>AVec& <T>AVec::operator -= (<T>AVec& b) +{ + check_len(b.capacity()); + <T>* u = b.vec(); + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ -= *u++; + return *this; +} + +<T>AVec& <T>AVec::product(<T>AVec& b) +{ + check_len(b.capacity()); + <T>* u = b.vec(); + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ *= *u++; + return *this; +} + +<T>AVec& <T>AVec::quotient(<T>AVec& b) +{ + check_len(b.capacity()); + <T>* u = b.vec(); + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ /= *u++; + return *this; +} + +<T>AVec& <T>AVec::operator += (<T&> b) +{ + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ += b; + return *this; +} + +<T>AVec& <T>AVec::operator -= (<T&> b) +{ + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ -= b; + return *this; +} + +<T>AVec& <T>AVec::operator *= (<T&> b) +{ + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ *= b; + return *this; +} + +<T>AVec& <T>AVec::operator /= (<T&> b) +{ + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ /= b; + return *this; +} + +<T> <T>AVec::max() +{ + if (len == 0) + return 0; + <T>* top = &(s[len]); + <T>* t = s; + <T> res = *t++; + for (; t < top; ++t) if (*t > res) res = *t; + return res; +} + +int <T>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; +} + +<T> <T>AVec::min() +{ + if (len == 0) + return 0; + <T>* top = &(s[len]); + <T>* t = s; + <T> res = *t++; + for (; t < top; ++t) if (*t < res) res = *t; + return res; +} + +int <T>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; +} + +<T> <T>AVec::sum() +{ + <T> res = 0; + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) res += *t++; + return res; +} + + +<T> <T>AVec::sumsq() +{ + <T> res = 0; + <T>* top = &(s[len]); + <T>* t = s; + for (; t < top; ++t) res += *t * *t; + return res; +} + +<T> operator * (<T>AVec& a, <T>AVec& b) +{ + a.check_len(b.capacity()); + <T>* top = &(a.vec()[a.capacity()]); + <T>* t = a.vec(); + <T>* u = b.vec(); + <T> res = 0; + while (t < top) res += *t++ * *u++; + return res; +} diff --git a/gnu/lib/libg++/g++-include/gen/AVec.hP b/gnu/lib/libg++/g++-include/gen/AVec.hP new file mode 100644 index 00000000000..9c57d204f7d --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/AVec.hP @@ -0,0 +1,123 @@ +// 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 _<T>AVec_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>AVec_h 1 + +#include "<T>.Vec.h" + +class <T>AVec : public <T>Vec +{ +protected: + void check_len(int l); + <T>* vec(); + <T>AVec(int l, <T>* d); + public: + <T>AVec (); + <T>AVec (int l); + <T>AVec (int l, <T&> fill_value); + <T>AVec (<T>AVec&); + ~<T>AVec (); + + <T>AVec& operator = (<T>AVec& a); + <T>AVec& operator = (<T&> fill_value); + +// vector by scalar -> vector operations + + friend <T>AVec operator + (<T>AVec& a, <T&> b); + friend <T>AVec operator - (<T>AVec& a, <T&> b); + friend <T>AVec operator * (<T>AVec& a, <T&> b); + friend <T>AVec operator / (<T>AVec& a, <T&> b); + + <T>AVec& operator += (<T&> b); + <T>AVec& operator -= (<T&> b); + <T>AVec& operator *= (<T&> b); + <T>AVec& operator /= (<T&> b); + +// vector by vector -> vector operations + + friend <T>AVec operator + (<T>AVec& a, <T>AVec& b); + friend <T>AVec operator - (<T>AVec& a, <T>AVec& b); + <T>AVec& operator += (<T>AVec& b); + <T>AVec& operator -= (<T>AVec& b); + + <T>AVec operator - (); + + friend <T>AVec product(<T>AVec& a, <T>AVec& b); + <T>AVec& product(<T>AVec& b); + friend <T>AVec quotient(<T>AVec& a, <T>AVec& b); + <T>AVec& quotient(<T>AVec& b); + +// vector -> scalar operations + + friend <T> operator * (<T>AVec& a, <T>AVec& b); + + <T> sum(); + <T> min(); + <T> max(); + <T> sumsq(); + +// indexing + + int min_index(); + int max_index(); + +// redundant but necesssary + friend <T>AVec concat(<T>AVec& a, <T>AVec& b); + friend <T>AVec map(<T>Mapper f, <T>AVec& a); + friend <T>AVec merge(<T>AVec& a, <T>AVec& b, <T>Comparator f); + friend <T>AVec combine(<T>Combiner f, <T>AVec& a, <T>AVec& b); + friend <T>AVec reverse(<T>AVec& a); + <T>AVec at(int from = 0, int n = -1); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>AVec::<T>AVec() {} +inline <T>AVec::<T>AVec(int l) :<T>Vec(l) {} +inline <T>AVec::<T>AVec(int l, <T&> fill_value) : <T>Vec (l, fill_value) {} +inline <T>AVec::<T>AVec(<T>AVec& v) :(v) {} +inline <T>AVec::<T>AVec(int l, <T>* d) :<T>Vec(l, d) {} +inline <T>AVec::~<T>AVec() {} + + +inline <T>* <T>AVec::vec() +{ + return s; +} + + +inline void <T>AVec::check_len(int l) +{ + if (l != len) + error("nonconformant vectors."); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/BSTSet.ccP b/gnu/lib/libg++/g++-include/gen/BSTSet.ccP new file mode 100644 index 00000000000..5edb1d62eb4 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/BSTSet.ccP @@ -0,0 +1,383 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.BSTSet.h" + + +/* + traversal primitives +*/ + + +<T>BSTNode* <T>BSTSet::leftmost() +{ + <T>BSTNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T>BSTNode* <T>BSTSet::rightmost() +{ + <T>BSTNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T>BSTNode* <T>BSTSet::succ(<T>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; + } + } +} + +<T>BSTNode* <T>BSTSet::pred(<T>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 <T>BSTSet::seek(<T&> key) +{ + <T>BSTNode* t = root; + for (;;) + { + if (t == 0) + return 0; + int comp = <T>CMP(key, t->item); + if (comp == 0) + return Pix(t); + else if (comp < 0) + t = t->lt; + else + t = t->rt; + } +} + + +Pix <T>BSTSet::add(<T&> item) +{ + if (root == 0) + { + ++count; + root = new <T>BSTNode(item); + return Pix(root); + } + + <T>BSTNode* t = root; + <T>BSTNode* p = root; + int comp; + for (;;) + { + if (t == 0) + { + ++count; + t = new <T>BSTNode(item); + if (comp > 0) + p->lt = t; + else + p->rt = t; + t->par = p; + return Pix(t); + } + p = t; + comp = <T>CMP(t->item, item); + if (comp == 0) + return Pix(t); + else if (comp > 0) + t = t->lt; + else + t = t->rt; + } +} + + +void <T>BSTSet::del(<T&> key) +{ + <T>BSTNode* t = root; + <T>BSTNode* p = root; + int comp; + for (;;) + { + if (t == 0) + return; + comp = <T>CMP(key, t->item); + if (comp == 0) + { + --count; + <T>BSTNode* repl; + if (t->lt == 0) + repl = t->rt; + else if (t->rt == 0) + repl = t->lt; + else + { + <T>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 <T>BSTSet::_kill(<T>BSTNode* t) +{ + if (t != 0) + { + _kill(t->lt); + _kill(t->rt); + delete t; + } +} + +<T>BSTNode* <T>BSTSet::_copy(<T>BSTNode* t) +{ + if (t == 0) + return 0; + else + { + <T>BSTNode* u = new <T>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 <T>BSTSet::operator == (<T>BSTSet& y) +{ + if (count != y.count) + return 0; + else + { + <T>BSTNode* t = leftmost(); + <T>BSTNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (!<T>EQ(t->item, u->item)) + return 0; + else + { + t = succ(t); + u = y.succ(u); + } + } + } +} + +int <T>BSTSet::operator <= (<T>BSTSet& y) +{ + if (count > y.count) + return 0; + else + { + <T>BSTNode* t = leftmost(); + <T>BSTNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (u == 0) + return 0; + int cmp = <T>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 <T>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; + <T>BSTNode* pseudo_root = (<T>BSTNode*)&fake_root; + + // phase 1: tree-to-vine + + <T>BSTNode* vine_tail = pseudo_root; + <T>BSTNode* remainder = root; + + while (remainder != 0) + { + if (remainder->lt == 0) + { + vine_tail = remainder; + remainder = remainder->rt; + } + else + { + <T>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 + + <T>BSTNode* scanner = pseudo_root; + while (compressions-- > 0) + { + <T>BSTNode* child = scanner->rt; + <T>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 <T>BSTSet::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T>BSTNode* trail = leftmost(); + <T>BSTNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/BSTSet.hP b/gnu/lib/libg++/g++-include/gen/BSTSet.hP new file mode 100644 index 00000000000..4ac9f4099dc --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/BSTSet.hP @@ -0,0 +1,166 @@ +// 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 _<T>BSTSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>BSTSet_h 1 + +#include "<T>.Set.h" + +#ifndef _<T>BSTNode +#define _<T>BSTNode 1 + +struct <T>BSTNode +{ + <T>BSTNode* lt; + <T>BSTNode* rt; + <T>BSTNode* par; + <T> item; + <T>BSTNode(<T&> h, <T>BSTNode* l=0, <T>BSTNode* r=0, + <T>BSTNode* p = 0); + ~<T>BSTNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>BSTNode::<T>BSTNode(<T&> h, <T>BSTNode* l, <T>BSTNode* r, + <T>BSTNode* p) +:item(h), lt(l), rt(r), par(p) {} + +inline <T>BSTNode::~<T>BSTNode() {} + +#endif + +typedef <T>BSTNode* <T>BSTNodePtr; + +#endif + +class <T>BSTSet : public <T>Set +{ +protected: + <T>BSTNode* root; + + <T>BSTNode* leftmost(); + <T>BSTNode* rightmost(); + <T>BSTNode* pred(<T>BSTNode* t); + <T>BSTNode* succ(<T>BSTNode* t); + void _kill(<T>BSTNode* t); + <T>BSTNode* _copy(<T>BSTNode* t); + +public: + <T>BSTSet(); + <T>BSTSet(<T>BSTSet& a); + ~<T>BSTSet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item); + + Pix last(); + void prev(Pix& i); + + int operator == (<T>BSTSet& b); + int operator != (<T>BSTSet& b); + int operator <= (<T>BSTSet& b); + + void balance(); + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>BSTSet::~<T>BSTSet() +{ + _kill(root); +} + +inline <T>BSTSet::<T>BSTSet() +{ + root = 0; + count = 0; +} + + +inline <T>BSTSet::<T>BSTSet(<T>BSTSet& a) +{ + count = a.count; + root = _copy(a.root); +} + +inline int <T>BSTSet::operator != (<T>BSTSet& b) +{ + return ! (*this == b); +} + +inline Pix <T>BSTSet::first() +{ + return Pix(leftmost()); +} + +inline Pix <T>BSTSet::last() +{ + return Pix(rightmost()); +} + +inline void <T>BSTSet::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T>BSTNode*)i)); +} + +inline void <T>BSTSet::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T>BSTNode*)i)); +} + +inline <T>& <T>BSTSet::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>BSTNode*)i)->item; +} + +inline void <T>BSTSet::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T>BSTSet::contains(<T&> key) +{ + return seek(key) != 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Bag.ccP b/gnu/lib/libg++/g++-include/gen/Bag.ccP new file mode 100644 index 00000000000..694c9b7c074 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Bag.ccP @@ -0,0 +1,79 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include "<T>.Bag.h" + +// error handling + +void <T>Bag::error(const char* msg) +{ + (*lib_error_handler)("Bag", msg); +} + + +Pix <T>Bag::seek(<T&> item, Pix i) +{ + if (i == 0) + i = first(); + else + next(i); + for (;i != 0 && (!(<T>EQ((*this)(i), item))); next(i)); + return i; +} + +int <T>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 <T>Bag::remove(<T&> item) +{ + int i = nof(item); + while (i-- > 0) del(item); +} + + +int <T>Bag::nof(<T&> item) +{ + int n = 0; + for (Pix p = first(); p; next(p)) if (<T>EQ((*this)(p), item)) ++n; + return n; +} + +void <T>Bag::clear() +{ + Pix i = first(); + while (i != 0) + { + del((*this)(i)); + i = first(); + } +} + + diff --git a/gnu/lib/libg++/g++-include/gen/Bag.hP b/gnu/lib/libg++/g++-include/gen/Bag.hP new file mode 100644 index 00000000000..af87a8ba534 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Bag.hP @@ -0,0 +1,87 @@ +// 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 _<T>Bag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Bag_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +class <T>Bag +{ +protected: + int count; + +public: + virtual ~<T>Bag(); + + int length(); // current number of items + int empty(); + + virtual Pix add(<T&> item) = 0; // add item; return Pix + + virtual void del(<T&> item) = 0; // delete 1 occurrence of item + virtual void remove(<T&> item); // delete all occurrences + virtual void clear(); // delete all items + + virtual int contains(<T&> item); // is item in Bag? + virtual int nof(<T&> 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 <T>& operator () (Pix i) = 0; // access item at i + + virtual Pix seek(<T&> 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 +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>Bag::~<T>Bag() {} + +inline int <T>Bag::length() +{ + return count; +} + +inline int <T>Bag::empty() +{ + return count == 0; +} + +inline int <T>Bag::contains(<T&> item) +{ + return seek(item) != 0; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/CHBag.ccP b/gnu/lib/libg++/g++-include/gen/CHBag.ccP new file mode 100644 index 00000000000..b7f97ec938c --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHBag.ccP @@ -0,0 +1,214 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.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(<T>CHNode* t) +{ + return ((((unsigned)t) & 1) == 0); +} + +static inline <T>CHNode* index_to_CHptr(int i) +{ + return (<T>CHNode*)((i << 1) + 1); +} + +static inline int CHptr_to_index(<T>CHNode* t) +{ + return ( ((unsigned) t) >> 1); +} + +<T>CHBag::<T>CHBag(unsigned int sz) +{ + tab = (<T>CHNode**)(new <T>CHNodePtr[size = sz]); + for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); + count = 0; +} + +<T>CHBag::<T>CHBag(<T>CHBag& a) +{ + tab = (<T>CHNode**)(new <T>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 <T>CHBag::seek(<T&> key, Pix i) +{ + <T>CHNode* p = (<T>CHNode*)i; + if (p == 0 || !<T>EQ(p->hd, key)) + { + unsigned int h = <T>HASH(key) % size; + for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(key, t->hd)) + return Pix(t); + } + else + { + for (p = p->tl; goodCHptr(p); p = p->tl) + if (<T>EQ(p->hd, key)) + return Pix(p); + } + return 0; +} + +int <T>CHBag::nof(<T&> key) +{ + int n = 0; + unsigned int h = <T>HASH(key) % size; + for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(key, t->hd)) ++n; + return n; +} + + +Pix <T>CHBag::add(<T&> item) +{ + unsigned int h = <T>HASH(item) % size; + <T>CHNode* t = new <T>CHNode(item); + t->tl = tab[h]; + tab[h] = t; + ++count; + return Pix(t); +} + +void <T>CHBag::del(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + <T>CHNode* t = tab[h]; + <T>CHNode* trail = t; + while (goodCHptr(t)) + { + if (<T>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 <T>CHBag::remove(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + <T>CHNode* t = tab[h]; + <T>CHNode* trail = t; + while (goodCHptr(t)) + { + if (<T>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 <T>CHBag::clear() +{ + for (unsigned int i = 0; i < size; ++i) + { + <T>CHNode* p = tab[i]; + tab[i] = index_to_CHptr(i+1); + while (goodCHptr(p)) + { + <T>CHNode* nxt = p->tl; + delete(p); + p = nxt; + } + } + count = 0; +} + +Pix <T>CHBag::first() +{ + for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); + return 0; +} + +void <T>CHBag::next(Pix& p) +{ + if (p == 0) return; + <T>CHNode* t = ((<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 <T>CHBag::OK() +{ + int v = tab != 0; + int n = 0; + for (unsigned int i = 0; i < size; ++i) + { + for (<T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/CHBag.hP b/gnu/lib/libg++/g++-include/gen/CHBag.hP new file mode 100644 index 00000000000..5254f8ff962 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHBag.hP @@ -0,0 +1,110 @@ +// 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 _<T>CHBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>CHBag_h 1 + +#include "<T>.Bag.h" + + +#ifndef _<T>CHNode_h +#define _<T>CHNode_h 1 + +struct <T>CHNode +{ + <T>CHNode* tl; + <T> hd; + <T>CHNode(); + <T>CHNode(<T&> h, <T>CHNode* t = 0); + ~<T>CHNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>CHNode::<T>CHNode() {} + +inline <T>CHNode::<T>CHNode(<T&> h, <T>CHNode* t) :hd(h), tl(t) {} + +inline <T>CHNode::~<T>CHNode() {} + +#endif + +typedef <T>CHNode* <T>CHNodePtr; + +#endif + + +class <T>CHBag : public <T>Bag +{ +protected: + <T>CHNode** tab; + unsigned int size; + +public: + <T>CHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY); + <T>CHBag(<T>CHBag& a); + ~<T>CHBag(); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int nof(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item, Pix from = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>CHBag::~<T>CHBag() +{ + clear(); + delete tab; +} + +inline int <T>CHBag::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T>CHBag::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>CHNode*)i)->hd; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/CHMap.ccP b/gnu/lib/libg++/g++-include/gen/CHMap.ccP new file mode 100644 index 00000000000..edb942f2963 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHMap.ccP @@ -0,0 +1,171 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.<C>.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(<T><C>CHNode* t) +{ + return ((((unsigned)t) & 1) == 0); +} + +static inline <T><C>CHNode* index_to_CHptr(int i) +{ + return (<T><C>CHNode*)((i << 1) + 1); +} + +static inline int CHptr_to_index(<T><C>CHNode* t) +{ + return ( ((unsigned) t) >> 1); +} + +<T><C>CHMap::<T><C>CHMap(<C&> dflt, unsigned int sz) + :<T><C>Map(dflt) +{ + tab = (<T><C>CHNode**)(new <T><C>CHNodePtr[size = sz]); + for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); + count = 0; +} + +<T><C>CHMap::<T><C>CHMap(<T><C>CHMap& a) :<T><C>Map(a.def) +{ + tab = (<T><C>CHNode**)(new <T><C>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 <T><C>CHMap::seek(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + for (<T><C>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(key, t->hd)) + return Pix(t); + + return 0; +} + + +<C>& <T><C>CHMap::operator [](<T&> item) +{ + unsigned int h = <T>HASH(item) % size; + + for (<T><C>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(item, t->hd)) + return t->cont; + + t = new <T><C>CHNode(item, def, tab[h]); + tab[h] = t; + ++count; + return t->cont; +} + + +void <T><C>CHMap::del(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + <T><C>CHNode* t = tab[h]; + <T><C>CHNode* trail = t; + while (goodCHptr(t)) + { + if (<T>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 <T><C>CHMap::clear() +{ + for (unsigned int i = 0; i < size; ++i) + { + <T><C>CHNode* p = tab[i]; + tab[i] = index_to_CHptr(i+1); + while (goodCHptr(p)) + { + <T><C>CHNode* nxt = p->tl; + delete(p); + p = nxt; + } + } + count = 0; +} + +Pix <T><C>CHMap::first() +{ + for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); + return 0; +} + +void <T><C>CHMap::next(Pix& p) +{ + <T><C>CHNode* t = ((<T><C>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 <T><C>CHMap::OK() +{ + int v = tab != 0; + int n = 0; + for (unsigned int i = 0; i < size; ++i) + { + for (<T><C>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/CHMap.hP b/gnu/lib/libg++/g++-include/gen/CHMap.hP new file mode 100644 index 00000000000..03479718be3 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHMap.hP @@ -0,0 +1,118 @@ +// 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 _<T><C>CHMap_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>CHMap_h 1 + +#include "<T>.<C>.Map.h" + +#ifndef _<T><C>CHNode_h +#define _<T><C>CHNode_h 1 + +struct <T><C>CHNode +{ + <T><C>CHNode* tl; + <T> hd; + <C> cont; + <T><C>CHNode(); + <T><C>CHNode(<T&> h, <C&> c, <T><C>CHNode* t = 0); + ~<T><C>CHNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>CHNode::<T><C>CHNode() {} + +inline <T><C>CHNode::<T><C>CHNode(<T&> h, <C&> c, <T><C>CHNode* t) + : hd(h), cont(c), tl(t) {} + +inline <T><C>CHNode::~<T><C>CHNode() {} + + +#endif + +typedef <T><C>CHNode* <T><C>CHNodePtr; + +#endif + + +class <T><C>CHMap : public <T><C>Map +{ +protected: + <T><C>CHNode** tab; + unsigned int size; + +public: + <T><C>CHMap(<C&> dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY); + <T><C>CHMap(<T><C>CHMap& a); + ~<T><C>CHMap(); + + <C>& operator [] (<T&> key); + + void del(<T&> key); + + Pix first(); + void next(Pix& i); + <T>& key(Pix i); + <C>& contents(Pix i); + + Pix seek(<T&> key); + int contains(<T&> key); + + void clear(); + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>CHMap::~<T><C>CHMap() +{ + clear(); + delete tab; +} + +inline int <T><C>CHMap::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T><C>CHMap::key(Pix p) +{ + if (p == 0) error("null Pix"); + return ((<T><C>CHNode*)p)->hd; +} + +inline <C>& <T><C>CHMap::contents(Pix p) +{ + if (p == 0) error("null Pix"); + return ((<T><C>CHNode*)p)->cont; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/CHSet.ccP b/gnu/lib/libg++/g++-include/gen/CHSet.ccP new file mode 100644 index 00000000000..07c57d34620 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHSet.ccP @@ -0,0 +1,276 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.CHSet.h" + +// A CHSet is implemented as an array (tab) of buckets, each of which +// contains a pointer to a list of <T>CHNodes. Each node contains a +// pointer to the next node in the list, and a pointer to the <T>. +// 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(<T>CHNode* t) +{ + return ((((unsigned)t) & 1) == 0); +} + +static inline <T>CHNode* index_to_CHptr(int i) +{ + return (<T>CHNode*)((i << 1) + 1); +} + +static inline int CHptr_to_index(<T>CHNode* t) +{ + return ( ((unsigned) t) >> 1); +} + +<T>CHSet::<T>CHSet(unsigned int sz) +{ + tab = (<T>CHNode**)(new <T>CHNodePtr[size = sz]); + for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1); + count = 0; +} + +<T>CHSet::<T>CHSet(<T>CHSet& a) +{ + tab = (<T>CHNode**)(new <T>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 <T>CHSet::seek(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(key, t->hd)) + return Pix(t); + + return 0; +} + + +Pix <T>CHSet::add(<T&> item) +{ + unsigned int h = <T>HASH(item) % size; + + for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) + if (<T>EQ(item, t->hd)) + return Pix(t); + + ++count; + t = new <T>CHNode(item, tab[h]); + tab[h] = t; + return Pix(t); +} + + +void <T>CHSet::del(<T&> key) +{ + unsigned int h = <T>HASH(key) % size; + + <T>CHNode* t = tab[h]; + <T>CHNode* trail = t; + while (goodCHptr(t)) + { + if (<T>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 <T>CHSet::clear() +{ + for (unsigned int i = 0; i < size; ++i) + { + <T>CHNode* p = tab[i]; + tab[i] = index_to_CHptr(i+1); + while (goodCHptr(p)) + { + <T>CHNode* nxt = p->tl; + delete(p); + p = nxt; + } + } + count = 0; +} + +Pix <T>CHSet::first() +{ + for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]); + return 0; +} + +void <T>CHSet::next(Pix& p) +{ + if (p == 0) return; + <T>CHNode* t = ((<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 <T>CHSet::operator == (<T>CHSet& b) +{ + if (count != b.count) + return 0; + else + { + <T>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 <T>CHSet::operator <= (<T>CHSet& b) +{ + if (count > b.count) + return 0; + else + { + for (unsigned int i = 0; i < size; ++i) + for (<T>CHNode* p = tab[i]; goodCHptr(p); p = p->tl) + if (b.seek(p->hd) == 0) + return 0; + return 1; + } +} + +void <T>CHSet::operator |= (<T>CHSet& b) +{ + if (&b == this || b.count == 0) + return; + for (unsigned int i = 0; i < b.size; ++i) + for (<T>CHNode* p = b.tab[i]; goodCHptr(p); p = p->tl) + add(p->hd); +} + +void <T>CHSet::operator &= (<T>CHSet& b) +{ + for (unsigned int i = 0; i < size; ++i) + { + <T>CHNode* t = tab[i]; + <T>CHNode* trail = t; + while (goodCHptr(t)) + { + <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 <T>CHSet::operator -= (<T>CHSet& b) +{ + for (unsigned int i = 0; i < size; ++i) + { + <T>CHNode* t = tab[i]; + <T>CHNode* trail = t; + while (goodCHptr(t)) + { + <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 <T>CHSet::OK() +{ + int v = tab != 0; + int n = 0; + for (unsigned int i = 0; i < size; ++i) + { + for (<T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/CHSet.hP b/gnu/lib/libg++/g++-include/gen/CHSet.hP new file mode 100644 index 00000000000..51cad80a95c --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/CHSet.hP @@ -0,0 +1,121 @@ +// 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 _<T>CHSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>CHSet_h 1 + +#include "<T>.Set.h" + + +#ifndef _<T>CHNode_h +#define _<T>CHNode_h 1 + +struct <T>CHNode +{ + <T>CHNode* tl; + <T> hd; + <T>CHNode(); + <T>CHNode(<T&> h, <T>CHNode* t = 0); + ~<T>CHNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>CHNode::<T>CHNode() {} + +inline <T>CHNode::<T>CHNode(<T&> h, <T>CHNode* t) : hd(h), tl(t) {} + +inline <T>CHNode::~<T>CHNode() {} + +#endif + +typedef <T>CHNode* <T>CHNodePtr; + +#endif + + +class <T>CHSet : public <T>Set +{ +protected: + <T>CHNode** tab; + unsigned int size; + +public: + <T>CHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY); + <T>CHSet(<T>CHSet& a); + ~<T>CHSet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item); + + void operator |= (<T>CHSet& b); + void operator -= (<T>CHSet& b); + void operator &= (<T>CHSet& b); + + int operator == (<T>CHSet& b); + int operator != (<T>CHSet& b); + int operator <= (<T>CHSet& b); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>CHSet::~<T>CHSet() +{ + clear(); + delete tab; +} + +inline int <T>CHSet::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T>CHSet::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>CHNode*)i)->hd; +} + +inline int <T>CHSet::operator != (<T>CHSet& b) +{ + return ! ((*this) == b); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/DLDeque.ccP b/gnu/lib/libg++/g++-include/gen/DLDeque.ccP new file mode 100644 index 00000000000..d5a0db7f910 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/DLDeque.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.DLDeque.h" diff --git a/gnu/lib/libg++/g++-include/gen/DLDeque.hP b/gnu/lib/libg++/g++-include/gen/DLDeque.hP new file mode 100644 index 00000000000..5ef7c4cdfc7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/DLDeque.hP @@ -0,0 +1,138 @@ +// 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 _<T>DLDeque_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>DLDeque_h + +#include "<T>.DLList.h" +#include "<T>.Deque.h" + +class <T>DLDeque : public <T>Deque +{ + <T>DLList p; + +public: + <T>DLDeque(); + <T>DLDeque(const <T>DLDeque& d); + ~<T>DLDeque(); + + void operator = (const <T>DLDeque&); + + void push(<T&> item); // insert at front + void enq(<T&> item); // insert at rear + + <T>& front(); + <T>& rear(); + + <T> deq(); + void del_front(); + void del_rear(); + + void clear(); + int empty(); + int full(); + int length(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>DLDeque::<T>DLDeque() : p() {} +inline <T>DLDeque::<T>DLDeque(const <T>DLDeque& d) : p(d.p) {} + +inline <T>DLDeque::~<T>DLDeque() {} + +inline void <T>DLDeque::push(<T&>item) +{ + p.prepend(item); +} + +inline void <T>DLDeque::enq(<T&>item) +{ + p.append(item); +} + +inline <T> <T>DLDeque::deq() +{ + return p.remove_front(); +} + +inline <T>& <T>DLDeque::front() +{ + return p.front(); +} + +inline <T>& <T>DLDeque::rear() +{ + return p.rear(); +} + +inline void <T>DLDeque::del_front() +{ + p.del_front(); +} + +inline void <T>DLDeque::del_rear() +{ + p.del_rear(); +} + +inline void <T>DLDeque::operator =(const <T>DLDeque& s) +{ + p.operator = (s.p); +} + + +inline int <T>DLDeque::empty() +{ + return p.empty(); +} + +inline int <T>DLDeque::full() +{ + return 0; +} + +inline int <T>DLDeque::length() +{ + return p.length(); +} + +inline int <T>DLDeque::OK() +{ + return p.OK(); +} + +inline void <T>DLDeque::clear() +{ + p.clear(); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/DLList.ccP b/gnu/lib/libg++/g++-include/gen/DLList.ccP new file mode 100644 index 00000000000..c9965a66179 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/DLList.ccP @@ -0,0 +1,317 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <values.h> +#include <stream.h> +#include "<T>.DLList.h" + +// error handling + + + +void <T>DLList::error(const char* msg) +{ + (*lib_error_handler)("DLList", msg); +} + +int <T>DLList::length() +{ + int l = 0; + <T>DLListNode* t = h; + if (t != 0) do { ++l; t = t->fd; } while (t != h); + return l; +} + +<T>DLList::<T>DLList(<T>DLList& a) +{ + if (a.h == 0) + h = 0; + else + { + <T>DLListNode* p = a.h; + <T>DLListNode* t = new <T>DLListNode(p->hd); + h = t; + p = p->fd; + while (p != a.h) + { + <T>DLListNode* n = new <T>DLListNode(p->hd); + t->fd = n; + n->bk = t; + t = n; + p = p->fd; + } + t->fd = h; + h->bk = t; + return; + } +} + +<T>DLList& <T>DLList::operator = (<T>DLList& a) +{ + if (h != a.h) + { + clear(); + if (a.h != 0) + { + <T>DLListNode* p = a.h; + <T>DLListNode* t = new <T>DLListNode(p->hd); + h = t; + p = p->fd; + while (p != a.h) + { + <T>DLListNode* n = new <T>DLListNode(p->hd); + t->fd = n; + n->bk = t; + t = n; + p = p->fd; + } + t->fd = h; + h->bk = t; + } + } + return *this; +} + +void <T>DLList::clear() +{ + if (h == 0) + return; + + <T>DLListNode* p = h->fd; + h->fd = 0; + h = 0; + + while (p != 0) + { + <T>DLListNode* nxt = p->fd; + delete(p); + p = nxt; + } +} + + +Pix <T>DLList::prepend(<T&> item) +{ + <T>DLListNode* t = new <T>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 <T>DLList::append(<T&> item) +{ + <T>DLListNode* t = new <T>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 <T>DLList::ins_after(Pix p, <T&> item) +{ + if (p == 0) return prepend(item); + <T>DLListNode* u = (<T>DLListNode*) p; + <T>DLListNode* t = new <T>DLListNode(item, u, u->fd); + u->fd->bk = t; + u->fd = t; + return Pix(t); +} + +Pix <T>DLList::ins_before(Pix p, <T&> item) +{ + if (p == 0) error("null Pix"); + <T>DLListNode* u = (<T>DLListNode*) p; + <T>DLListNode* t = new <T>DLListNode(item, u->bk, u); + u->bk->fd = t; + u->bk = t; + if (u == h) h = t; + return Pix(t); +} + +void <T>DLList::join(<T>DLList& b) +{ + <T>DLListNode* t = b.h; + b.h = 0; + if (h == 0) + h = t; + else if (t != 0) + { + <T>DLListNode* l = t->bk; + h->bk->fd = t; + t->bk = h->bk; + h->bk = l; + l->fd = h; + } +} + +int <T>DLList::owns(Pix p) +{ + <T>DLListNode* t = h; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->fd; + } while (t != h); + } + return 0; +} + +void <T>DLList::del(Pix& p, int dir) +{ + if (p == 0) error("null Pix"); + <T>DLListNode* t = (<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; +} + +<T> <T>DLList::remove_front() +{ + if (h == 0) + error("remove_front of empty list"); + <T>DLListNode* t = h; + <T> 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 <T>DLList::del_front() +{ + if (h == 0) + error("del_front of empty list"); + <T>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; +} + +<T> <T>DLList::remove_rear() +{ + if (h == 0) + error("remove_rear of empty list"); + <T>DLListNode* t = h->bk; + <T> 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 <T>DLList::del_rear() +{ + if (h == 0) + error("del_rear of empty list"); + <T>DLListNode* t = h->bk; + if (h->fd == h) + h = 0; + else + { + t->fd->bk = t->bk; + t->bk->fd = t->fd; + } + delete t; +} + + +int <T>DLList::OK() +{ + int v = 1; + if (h != 0) + { + <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/DLList.hP b/gnu/lib/libg++/g++-include/gen/DLList.hP new file mode 100644 index 00000000000..511c7b55235 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/DLList.hP @@ -0,0 +1,170 @@ +// 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 _<T>DLList_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>DLList_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +#ifndef _<T>DLListNode_h +#define _<T>DLListNode_h 1 + +struct <T>DLListNode +{ + <T>DLListNode* bk; + <T>DLListNode* fd; + <T> hd; + <T>DLListNode(); + <T>DLListNode(<T&> h, + <T>DLListNode* p = 0, + <T>DLListNode* n = 0); + ~<T>DLListNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>DLListNode::<T>DLListNode() {} + +inline <T>DLListNode::<T>DLListNode(<T&> h, <T>DLListNode* p, + <T>DLListNode* n) + :hd(h), bk(p), fd(n) {} + +inline <T>DLListNode::~<T>DLListNode() {} + +#endif + +typedef <T>DLListNode* <T>DLListNodePtr; + +#endif + +class <T>DLList +{ + friend class <T>DLListTrav; + + <T>DLListNode* h; + +public: + <T>DLList(); + <T>DLList(<T>DLList& a); + ~<T>DLList(); + + <T>DLList& operator = (<T>DLList& a); + + int empty(); + int length(); + + void clear(); + + Pix prepend(<T&> item); + Pix append(<T&> item); + void join(<T>DLList&); + + <T>& front(); + <T> remove_front(); + void del_front(); + + <T>& rear(); + <T> remove_rear(); + void del_rear(); + + <T>& operator () (Pix p); + Pix first(); + Pix last(); + void next(Pix& p); + void prev(Pix& p); + int owns(Pix p); + Pix ins_after(Pix p, <T&> item); + Pix ins_before(Pix p, <T&> item); + void del(Pix& p, int dir = 1); + + void error(const char* msg); + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>DLList::~<T>DLList() +{ + clear(); +} + +inline <T>DLList::<T>DLList() +{ + h = 0; +} + +inline int <T>DLList::empty() +{ + return h == 0; +} + + +inline void <T>DLList::next(Pix& p) +{ + p = (p == 0 || p == h->bk)? 0 : Pix(((<T>DLListNode*)p)->fd); +} + +inline void <T>DLList::prev(Pix& p) +{ + p = (p == 0 || p == h)? 0 : Pix(((<T>DLListNode*)p)->bk); +} + +inline Pix <T>DLList::first() +{ + return Pix(h); +} + +inline Pix <T>DLList::last() +{ + return (h == 0)? 0 : Pix(h->bk); +} + +inline <T>& <T>DLList::operator () (Pix p) +{ + if (p == 0) error("null Pix"); + return ((<T>DLListNode*)p)->hd; +} + +inline <T>& <T>DLList::front() +{ + if (h == 0) error("front: empty list"); + return h->hd; +} + +inline <T>& <T>DLList::rear() +{ + if (h == 0) error("rear: empty list"); + return h->bk->hd; +} + + + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Deque.ccP b/gnu/lib/libg++/g++-include/gen/Deque.ccP new file mode 100644 index 00000000000..79a9b72c875 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Deque.ccP @@ -0,0 +1,11 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.Deque.h" + +<T>Deque::~<T>Deque() {} + +void <T>Deque::error(const char* msg) +{ + (*lib_error_handler)("Deque", msg); +} diff --git a/gnu/lib/libg++/g++-include/gen/Deque.hP b/gnu/lib/libg++/g++-include/gen/Deque.hP new file mode 100644 index 00000000000..a82607bec89 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Deque.hP @@ -0,0 +1,67 @@ +// 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 _<T>Deque_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Deque_h + +#include <builtin.h> + +#include "<T>.defs.h" + +class <T>Deque +{ +public: + <T>Deque(); + ~<T>Deque(); + + virtual void push(<T&> item) = 0; // insert at front + virtual void enq(<T&> item) = 0; // insert at rear + + virtual <T>& front() = 0; + virtual <T>& rear() = 0; + + virtual <T> 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*); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) +inline <T>Deque::<T>Deque() {} +#endif + +#endif diff --git a/gnu/lib/libg++/g++-include/gen/FPQueue.ccP b/gnu/lib/libg++/g++-include/gen/FPQueue.ccP new file mode 100644 index 00000000000..a358cacb60e --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPQueue.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.FPQueue.h" diff --git a/gnu/lib/libg++/g++-include/gen/FPQueue.hP b/gnu/lib/libg++/g++-include/gen/FPQueue.hP new file mode 100644 index 00000000000..9fcb81b58a3 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPQueue.hP @@ -0,0 +1,121 @@ +// 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 _<T>FPQueue_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>FPQueue_h + +#include "<T>.FPlex.h" +#include "<T>.Queue.h" + +class <T>FPQueue : public <T>Queue +{ + <T>FPlex p; + +public: + <T>FPQueue(int chunksize = DEFAULT_<T>PLEX_CHUNK_SIZE); + <T>FPQueue(const <T>FPQueue& q); + ~<T>FPQueue(); + + void operator = (const <T>FPQueue&); + + void enq(<T&> item); + <T> deq(); + <T>& front(); + void del_front(); + + void clear(); + int empty(); + int full(); + int length(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>FPQueue::<T>FPQueue(int chunksize) : p(chunksize) {} +inline <T>FPQueue::<T>FPQueue(const <T>FPQueue& q) : p(q.p) {} + +inline <T>FPQueue::~<T>FPQueue() {} + +inline void <T>FPQueue::enq(<T&>item) +{ + p.add_high(item); +} + +inline <T> <T>FPQueue::deq() +{ + <T> res = p.low_element(); + p.del_low(); + return res; +} + +inline <T>& <T>FPQueue::front() +{ + return p.low_element(); +} + + +inline void <T>FPQueue::del_front() +{ + p.del_low(); +} + +inline void <T>FPQueue::operator =(const <T>FPQueue& s) +{ + p = s.p; +} + +inline int <T>FPQueue::empty() +{ + return p.empty(); +} + +inline int <T>FPQueue::full() +{ + return p.full(); +} + +inline int <T>FPQueue::length() +{ + return p.length(); +} + +inline int <T>FPQueue::OK() +{ + return p.OK(); +} + +inline void <T>FPQueue::clear() +{ + p.clear(); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/FPStack.ccP b/gnu/lib/libg++/g++-include/gen/FPStack.ccP new file mode 100644 index 00000000000..954991193b7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPStack.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.FPStack.h" diff --git a/gnu/lib/libg++/g++-include/gen/FPStack.hP b/gnu/lib/libg++/g++-include/gen/FPStack.hP new file mode 100644 index 00000000000..1ec4673e484 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPStack.hP @@ -0,0 +1,123 @@ +// 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 _<T>FPStack_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>FPStack_h + +#include "<T>.FPlex.h" +#include "<T>.Stack.h" + +class <T>FPStack : public <T>Stack +{ + <T>FPlex p; + +public: + <T>FPStack(int chunksize = DEFAULT_<T>PLEX_CHUNK_SIZE); + <T>FPStack(const <T>FPStack& s); + ~<T>FPStack(); + + void operator = (const <T>FPStack&); + + void push(<T&> item); + <T> pop(); + <T>& top(); + void del_top(); + + int empty(); + int full(); + int length(); + + void clear(); + + int OK(); + +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>FPStack::<T>FPStack(int chunksize) : p(chunksize) {} +inline <T>FPStack::<T>FPStack(const <T>FPStack& s) : p(s.p) {} + +inline <T>FPStack::~<T>FPStack() {} + +inline void <T>FPStack::push(<T&>item) +{ + p.add_high(item); +} + +inline <T> <T>FPStack::pop() +{ + <T> res = p.high_element(); + p.del_high(); + return res; +} + +inline <T>& <T>FPStack::top() +{ + return p.high_element(); +} + +inline void <T>FPStack::del_top() +{ + p.del_high(); +} + +inline void <T>FPStack::operator =(const <T>FPStack& s) +{ + p = s.p; +} + +inline int <T>FPStack::empty() +{ + return p.empty(); +} + +inline int <T>FPStack::full() +{ + return p.full(); +} + +inline int <T>FPStack::length() +{ + return p.length(); +} + +inline int <T>FPStack::OK() +{ + return p.OK(); +} + +inline void <T>FPStack::clear() +{ + p.clear(); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/FPlex.ccP b/gnu/lib/libg++/g++-include/gen/FPlex.ccP new file mode 100644 index 00000000000..235d2908756 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPlex.ccP @@ -0,0 +1,182 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.FPlex.h" + + +<T>FPlex:: <T>FPlex() +{ + lo = fnc = 0; + csize = DEFAULT_INITIAL_CAPACITY; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, lo, lo, fnc, csize); +} + +<T>FPlex:: <T>FPlex(int maxsize) +{ + if (maxsize == 0) error("invalid constructor specification"); + lo = fnc = 0; + if (maxsize > 0) + { + csize = maxsize; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, lo, lo, fnc, csize); + } + else + { + csize = -maxsize; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, maxsize, lo, fnc, fnc); + } +} + + +<T>FPlex:: <T>FPlex(int l, int maxsize) +{ + if (maxsize == 0) error("invalid constructor specification"); + lo = fnc = l; + if (maxsize > 0) + { + csize = maxsize; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, lo, lo, fnc, csize+lo); + } + else + { + csize = -maxsize; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, maxsize+lo, lo, fnc, fnc); + } +} + +<T>FPlex:: <T>FPlex(int l, int hi, const <T&> initval, int maxsize) +{ + lo = l; + fnc = hi + 1; + if (maxsize >= 0) + { + csize = maxsize; + if (csize < fnc - lo) + csize = fnc - lo; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, lo, lo, fnc, csize); + } + else + { + csize = -maxsize; + if (csize < fnc - lo) + csize = fnc - lo; + <T>* data = new <T>[csize]; + hd = new <T>IChunk(data, -csize, lo, fnc, fnc); + } + fill(initval); +} + +<T>FPlex::<T>FPlex(const <T>FPlex& a) +{ + lo = a.lo; + fnc = a.fnc; + csize = fnc - lo; + if (csize < a.csize) csize = a.csize; + <T>* data = new <T> [csize]; + hd = new <T>IChunk(data, lo, lo, fnc, lo+csize); + for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; +} + +void <T>FPlex::operator= (const <T>FPlex& a) +{ + if (&a != this) + { + del_chunk(hd); + lo = a.lo; + fnc = a.fnc; + csize = fnc - lo; + if (csize < a.csize) csize = a.csize; + <T>* data = new <T> [csize]; + hd = new <T>IChunk(data, lo, lo, fnc, lo+csize); + for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i]; + } +} + + +void <T>FPlex::append (const <T>FPlex& a) +{ + for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); +} + +void <T>FPlex::prepend (const <T>FPlex& a) +{ + for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); +} + +void <T>FPlex::reverse() +{ + <T> 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 <T>FPlex::fill(const <T&> x) +{ + for (int i = lo; i < fnc; ++i) (*this)[i] = x; +} + +void <T>FPlex::fill(const <T&> x, int lo, int hi) +{ + for (int i = lo; i <= hi; ++i) (*this)[i] = x; +} + +void <T>FPlex::clear() +{ + if (fnc != lo) + { + hd->clear(lo); + fnc = lo; + } +} + +int <T>FPlex::OK () const +{ + int v = hd != 0; // hd exists + v &= hd-><T>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; +} + diff --git a/gnu/lib/libg++/g++-include/gen/FPlex.hP b/gnu/lib/libg++/g++-include/gen/FPlex.hP new file mode 100644 index 00000000000..2fda48d6226 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/FPlex.hP @@ -0,0 +1,263 @@ +// 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 _<T>FPlex_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>FPlex_h 1 + +#include "<T>.Plex.h" + +class <T>FPlex : public <T>Plex +{ +public: + <T>FPlex(); // set low = 0; + // fence = 0; + // csize = default + + <T>FPlex(int maxsize); // low = 0; + // fence = 0; + // csize = maxsize + + <T>FPlex(int lo, // low = lo; + int maxsize); // fence=lo + // csize = maxsize + + <T>FPlex(int lo, // low = lo + int hi, // fence = hi+1 + const <T&> initval,// fill with initval, + int maxsize = 0); // csize = maxsize + // or fence - lo if 0 + + <T>FPlex(const <T>FPlex&); // X(X&) + + ~<T>FPlex(); + + void operator= (const <T>FPlex&); + +// virtuals + + <T>& high_element (); + <T>& low_element (); + + const <T>& high_element () const; + const <T>& low_element () const; + + Pix first() const; + Pix last() const; + void prev(Pix& ptr) const; + void next(Pix& ptr) const; + int owns(Pix p) const; + <T>& operator () (Pix p); + const <T>& 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; + <T>& operator [] (int index); + const <T>& 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 <T&> elem); + int del_high (); + int add_low (const <T&> elem); + int del_low (); + + void fill(const <T&> x); + void fill(const <T&> x, int from, int to); + void clear(); + void reverse(); + void append(const <T>FPlex& a); + void prepend(const <T>FPlex& a); + + int OK () const; +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline int <T>FPlex::valid (int idx) const +{ + return idx >= lo && idx < fnc; +} + +inline int <T>FPlex::low() const +{ + return lo; +} + +inline int <T>FPlex::high() const +{ + return fnc - 1; +} + +inline Pix <T>FPlex::first() const +{ + return (Pix)(hd-><T>IChunk::first_pointer()); +} + +inline void <T>FPlex::prev(Pix& p) const +{ + p = Pix(hd-><T>IChunk::pred((<T>*) p)); +} + +inline void <T>FPlex::next(Pix& p) const +{ + p = Pix(hd-><T>IChunk::succ((<T>*) p)); +} + +inline Pix <T>FPlex::last() const +{ + return Pix(hd-><T>IChunk::last_pointer()); +} + +inline int <T>FPlex::full () const +{ + return fnc - lo == csize; +} + +inline void <T>FPlex::prev(int& idx) const +{ + --idx; +} + +inline void <T>FPlex::next(int& idx) const +{ + ++idx; +} + +inline <T>& <T>FPlex:: operator [] (int idx) +{ + if (idx < lo || idx >= fnc) index_error(); + return *(hd->pointer_to(idx)); +} + +inline <T>& <T>FPlex:: operator () (Pix p) +{ + return *((<T>*)p); +} + +inline <T>& <T>FPlex::low_element () +{ + if (empty()) index_error(); + return *(hd->pointer_to(lo)); +} + +inline <T>& <T>FPlex::high_element () +{ + if (empty()) index_error(); + return *(hd->pointer_to(fnc - 1)); +} + +inline const <T>& <T>FPlex:: operator [] (int idx) const +{ + if (idx < lo || idx >= fnc) index_error(); + return *(hd->pointer_to(idx)); +} + +inline const <T>& <T>FPlex:: operator () (Pix p) const +{ + return *((const <T>*)p); +} + +inline const <T>& <T>FPlex::low_element () const +{ + if (empty()) index_error(); + return *(hd->pointer_to(lo)); +} + +inline const <T>& <T>FPlex::high_element () const +{ + if (empty()) index_error(); + return *(hd->pointer_to(fnc - 1)); +} + +inline int <T>FPlex::can_add_high() const +{ + return hd->can_grow_high(); +} + +inline int <T>FPlex::can_add_low() const +{ + return hd->can_grow_low(); +} + +inline int <T>FPlex::add_high(const <T&> elem) +{ + if (!can_add_high()) full_error(); + *((hd-><T>IChunk::grow_high())) = elem; + return fnc++; +} + +inline int <T>FPlex::del_high () +{ + if (empty()) empty_error(); + hd-><T>IChunk::shrink_high(); + return --fnc - 1; +} + +inline int <T>FPlex::add_low (const <T&> elem) +{ + if (!can_add_low()) full_error(); + *((hd-><T>IChunk::grow_low())) = elem; + return --lo; +} + +inline int <T>FPlex::del_low () +{ + if (empty()) empty_error(); + hd-><T>IChunk::shrink_low(); + return ++lo; +} + +inline int <T>FPlex::owns (Pix p) const +{ + return hd->actual_pointer((<T>*)p); +} + +inline int <T>FPlex::Pix_to_index(Pix p) const +{ + if (!hd->actual_pointer((const <T>*)p)) index_error(); + return hd->index_of((const <T>*)p); +} + +inline Pix <T>FPlex::index_to_Pix(int idx) const +{ + if (idx < lo || idx >= fnc) index_error(); + return Pix(hd->pointer_to(idx)); +} + +inline <T>FPlex::~<T>FPlex() {} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/List.ccP b/gnu/lib/libg++/g++-include/gen/List.ccP new file mode 100644 index 00000000000..75c09a92f44 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/List.ccP @@ -0,0 +1,959 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include "<T>.List.h" + +<T>ListNode Nil<T>ListNode; + +class init_Nil<T>ListNode +{ +public: + inline init_Nil<T>ListNode() + { + Nil<T>ListNode.tl = &Nil<T>ListNode; + Nil<T>ListNode.ref = -1; + } +}; + +static init_Nil<T>ListNode Nil<T>ListNode_initializer; + +<T>List& <T>List::operator = (<T>List& a) +{ + reference(a.P); + dereference(P); + P = a.P; + return *this; +} + +<T> <T>List::pop() +{ + <T> res = P->hd; + <T>ListNode* tail = P->tl; + reference(tail); + dereference(P); + P = tail; + return res; +} + +void <T>List::set_tail(<T>List& a) +{ + reference(a.P); + dereference(P->tl); + P->tl = a.P; +} + +<T>List <T>List::nth(int n) +{ + for (<T>ListNode* p = P; n-- > 0; p = p->tl); + reference(p); + return <T>List(p); +} + +<T>List <T>List::last() +{ + <T>ListNode* p = P; + if (p != &Nil<T>ListNode) while (p->tl != &Nil<T>ListNode) p = p->tl; + reference(p); + return <T>List(p); +} + +void <T>List::append(<T>List& l) +{ + <T>ListNode* p = P; + <T>ListNode* a = l.P; + reference(a); + if (p != &Nil<T>ListNode) + { + while (p->tl != &Nil<T>ListNode) p = p->tl; + p->tl = a; + } + else + P = a; +} + +int <T>List::length() +{ + int l = 0; + for (<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) ++l; + return l; +} + +<T>& <T>List::operator [] (int n) +{ + for (<T>ListNode* p = P; n-- > 0; p = p->tl); + return (p->hd); +} + +int operator == (<T>List& x, <T>List& y) +{ + <T>ListNode* a = x.P; + <T>ListNode* b = y.P; + + for (;;) + { + if (a == &Nil<T>ListNode) + return b == &Nil<T>ListNode; + else if (b == &Nil<T>ListNode) + return 0; + else if (a->hd == b->hd) + { + a = a->tl; + b = b->tl; + } + else + return 0; + } +} + + +void <T>List::apply(<T>Procedure f) +{ + for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) + (*f)((p->hd)); +} + +void <T>List::subst(<T&> old, <T&> repl) +{ + for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) + if (p->hd == old) + p->hd = repl; +} + +<T> <T>List::reduce(<T>Combiner f, <T&> base) +{ + <T> r = base; + for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) + r = (*f)(r, (p->hd)); + return r; +} + +int <T>List::position(<T&> targ) +{ + int l = 0; + <T>ListNode* p = P; + for (;;) + { + if (p == &Nil<T>ListNode) + return -1; + else if (p->hd == targ) + return l; + else + { + ++l; + p = p->tl; + } + } +} + +int <T>List::contains(<T&> targ) +{ + <T>ListNode* p = P; + for (;;) + { + if (p == &Nil<T>ListNode) + return 0; + else if (p->hd == targ) + return 1; + else + p = p->tl; + } +} + +<T>List <T>List::find(<T&> targ) +{ + for (<T>ListNode* p = P; p != &Nil<T>ListNode && !(p->hd == targ); p=p->tl); + reference(p); + return <T>List(p); +} + +Pix <T>List::seek(<T&> targ) +{ + <T>ListNode* p = P; + for (;;) + { + if (p == &Nil<T>ListNode) + return 0; + else if (p->hd == targ) + return Pix(p); + else + p = p->tl; + } +} + +int <T>List::owns(Pix i) +{ + <T>ListNode* p = P; + for (;;) + { + if (p == &Nil<T>ListNode) + return 0; + else if (Pix(p) == i) + return 1; + else + p = p->tl; + } +} + +<T>List <T>List::find(<T>List& target) +{ + <T>ListNode* targ = target.P; + if (targ == &Nil<T>ListNode) + return <T>List(targ); + + <T>ListNode* p = P; + while (p != &Nil<T>ListNode) + { + if (p->hd == targ->hd) + { + <T>ListNode* a = p->tl; + <T>ListNode* t = targ->tl; + for(;;) + { + if (t == &Nil<T>ListNode) + { + reference(p); + return <T>List(p); + } + else if (a == &Nil<T>ListNode || !(a->hd == t->hd)) + break; + else + { + a = a->tl; + t = t->tl; + } + } + } + p = p->tl; + } + return <T>List(&Nil<T>ListNode); +} + +int <T>List::contains(<T>List& target) +{ + <T>ListNode* targ = target.P; + if (targ == &Nil<T>ListNode) + return 0; + + <T>ListNode* p = P; + while (p != &Nil<T>ListNode) + { + if (p->hd == targ->hd) + { + <T>ListNode* a = p->tl; + <T>ListNode* t = targ->tl; + for(;;) + { + if (t == &Nil<T>ListNode) + return 1; + else if (a == &Nil<T>ListNode || !(a->hd == t->hd)) + break; + else + { + a = a->tl; + t = t->tl; + } + } + } + p = p->tl; + } + return 0; +} + +void <T>List::del(<T&> targ) +{ + <T>ListNode* h = P; + + for (;;) + { + if (h == &Nil<T>ListNode) + { + P = h; + return; + } + else if (h->hd == targ) + { + <T>ListNode* nxt = h->tl; + reference(nxt); + dereference(h); + h = nxt; + } + else + break; + } + + <T>ListNode* trail = h; + <T>ListNode* p = h->tl; + while (p != &Nil<T>ListNode) + { + if (p->hd == targ) + { + <T>ListNode* nxt = p->tl; + reference(nxt); + dereference(p); + trail->tl = nxt; + p = nxt; + } + else + { + trail = p; + p = p->tl; + } + } + P = h; +} + +void <T>List::del(<T>Predicate f) +{ + <T>ListNode* h = P; + for (;;) + { + if (h == &Nil<T>ListNode) + { + P = h; + return; + } + else if ((*f)(h->hd)) + { + <T>ListNode* nxt = h->tl; + reference(nxt); + dereference(h); + h = nxt; + } + else + break; + } + + <T>ListNode* trail = h; + <T>ListNode* p = h->tl; + while (p != &Nil<T>ListNode) + { + if ((*f)(p->hd)) + { + <T>ListNode* nxt = p->tl; + reference(nxt); + dereference(p); + trail->tl = nxt; + p = nxt; + } + else + { + trail = p; + p = p->tl; + } + } + P = h; +} + +void <T>List::select(<T>Predicate f) +{ + <T>ListNode* h = P; + for (;;) + { + if (h == &Nil<T>ListNode) + { + P = h; + return; + } + else if (!(*f)(h->hd)) + { + <T>ListNode* nxt = h->tl; + reference(nxt); + dereference(h); + h = nxt; + } + else + break; + } + <T>ListNode* trail = h; + <T>ListNode* p = h->tl; + while (p != &Nil<T>ListNode) + { + if (!(*f)(p->hd)) + { + <T>ListNode* nxt = p->tl; + reference(nxt); + dereference(p); + trail->tl = nxt; + p = nxt; + } + else + { + trail = p; + p = p->tl; + } + } + P = h; +} + +void <T>List::reverse() +{ + <T>ListNode* l = &Nil<T>ListNode; + <T>ListNode* p = P; + while (p != &Nil<T>ListNode) + { + <T>ListNode* nxt = p->tl; + p->tl = l; + l = p; + p = nxt; + } + P = l; +} + + +<T>List copy(<T>List& x) +{ + <T>ListNode* a = x.P; + if (a == &Nil<T>ListNode) + return <T>List(a); + else + { + <T>ListNode* h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + } + trail->tl = &Nil<T>ListNode; + return <T>List(h); + } +} + + +<T>List subst(<T&> old, <T&> repl, <T>List& x) +{ + <T>ListNode* a = x.P; + if (a == &Nil<T>ListNode) + return <T>List(a); + else + { + <T>ListNode* h = new <T>ListNode; + h->ref = 1; + if (a->hd == old) + h->hd = repl; + else + h->hd = a->hd; + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new <T>ListNode; + n->ref = 1; + if (a->hd == old) + n->hd = repl; + else + n->hd = a->hd; + trail->tl = n; + trail = n; + } + trail->tl = &Nil<T>ListNode; + return <T>List(h); + } +} + +<T>List combine(<T>Combiner f, <T>List& x, <T>List& y) +{ + <T>ListNode* a = x.P; + <T>ListNode* b = y.P; + if (a == &Nil<T>ListNode || b == &Nil<T>ListNode) + return <T>List(&Nil<T>ListNode); + else + { + <T>ListNode* h = new<T>ListNode((*f)(a->hd, b->hd)); + <T>ListNode* trail = h; + a = a->tl; + b = b->tl; + while (a != &Nil<T>ListNode && b != &Nil<T>ListNode) + { + <T>ListNode* n = new<T>ListNode((*f)(a->hd, b->hd)); + trail->tl = n; + trail = n; + a = a->tl; + b = b->tl; + } + trail->tl = &Nil<T>ListNode; + return <T>List(h); + } +} + +<T>List reverse(<T>List& x) +{ + <T>ListNode* a = x.P; + if (a == &Nil<T>ListNode) + return <T>List(a); + else + { + <T>ListNode* l = new<T>ListNode(a->hd); + l->tl = &Nil<T>ListNode; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new<T>ListNode(a->hd); + n->tl = l; + l = n; + } + return <T>List(l); + } +} + +<T>List append(<T>List& x, <T>List& y) +{ + <T>ListNode* a = x.P; + <T>ListNode* b = y.P; + reference(b); + if (a != &Nil<T>ListNode) + { + <T>ListNode* h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + } + trail->tl = b; + return <T>List(h); + } + else + return <T>List(b); +} + +void <T>List::prepend(<T>List& y) +{ + <T>ListNode* b = y.P; + if (b != &Nil<T>ListNode) + { + <T>ListNode* h = new<T>ListNode(b->hd); + <T>ListNode* trail = h; + for(b = b->tl; b != &Nil<T>ListNode; b = b->tl) + { + <T>ListNode* n = new<T>ListNode(b->hd); + trail->tl = n; + trail = n; + } + trail->tl = P; + P = h; + } +} + +<T>List concat(<T>List& x, <T>List& y) +{ + <T>ListNode* a = x.P; + <T>ListNode* b = y.P; + if (a != &Nil<T>ListNode) + { + <T>ListNode* h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + }; + for(;b != &Nil<T>ListNode; b = b->tl) + { + <T>ListNode* n = new<T>ListNode(b->hd); + trail->tl = n; + trail = n; + } + trail->tl = &Nil<T>ListNode; + return <T>List(h); + } + else if (b != &Nil<T>ListNode) + { + <T>ListNode* h = new<T>ListNode(b->hd); + <T>ListNode* trail = h; + for(b = b->tl; b != &Nil<T>ListNode; b = b->tl) + { + <T>ListNode* n = new<T>ListNode(b->hd); + trail->tl = n; + trail = n; + } + trail->tl = &Nil<T>ListNode; + return <T>List(h); + } + else + return <T>List(&Nil<T>ListNode); +} + +<T>List select(<T>Predicate f, <T>List& x) +{ + <T>ListNode* a = x.P; + <T>ListNode* h = &Nil<T>ListNode; + while (a != &Nil<T>ListNode) + { + if ((*f)(a->hd)) + { + h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + if ((*f)(a->hd)) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + } + } + trail->tl = &Nil<T>ListNode; + break; + } + else + a = a->tl; + } + return <T>List(h); +} + +<T>List remove(<T>Predicate f, <T>List& x) +{ + <T>ListNode* a = x.P; + <T>ListNode* h = &Nil<T>ListNode; + while (a != &Nil<T>ListNode) + { + if (!(*f)(a->hd)) + { + h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + if (!(*f)(a->hd)) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + } + } + trail->tl = &Nil<T>ListNode; + break; + } + else + a = a->tl; + } + return <T>List(h); +} + +<T>List remove(<T&> targ, <T>List& x) +{ + <T>ListNode* a = x.P; + <T>ListNode* h = &Nil<T>ListNode; + while (a != &Nil<T>ListNode) + { + if (!(a->hd == targ)) + { + h = new<T>ListNode(a->hd); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + if (!(a->hd == targ)) + { + <T>ListNode* n = new<T>ListNode(a->hd); + trail->tl = n; + trail = n; + } + } + trail->tl = &Nil<T>ListNode; + break; + } + else + a = a->tl; + } + return <T>List(h); +} + +<T>List map(<T>Mapper f, <T>List& x) +{ + <T>ListNode* a = x.P; + <T>ListNode* h = &Nil<T>ListNode; + if (a != &Nil<T>ListNode) + { + h = new<T>ListNode((*f)(a->hd)); + <T>ListNode* trail = h; + for(a = a->tl; a != &Nil<T>ListNode; a = a->tl) + { + <T>ListNode* n = new<T>ListNode((*f)(a->hd)); + trail->tl = n; + trail = n; + } + trail->tl = &Nil<T>ListNode; + } + return <T>List(h); +} + + +<T>List merge(<T>List& x, <T>List& y, <T>Comparator f) +{ + <T>ListNode* a = x.P; + <T>ListNode* b = y.P; + + if (a == &Nil<T>ListNode) + { + if (b == &Nil<T>ListNode) + return <T>List(&Nil<T>ListNode); + else + return copy(y); + } + else if (b == &Nil<T>ListNode) + return copy(x); + + <T>ListNode* h = new <T>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; + } + + <T>ListNode* r = h; + + for(;;) + { + if (a == &Nil<T>ListNode) + { + while (b != &Nil<T>ListNode) + { + <T>ListNode* n = new <T>ListNode; + n->ref = 1; + n->hd = b->hd; + r->tl = n; + r = n; + b = b->tl; + } + r->tl = &Nil<T>ListNode; + return <T>List(h); + } + else if (b == &Nil<T>ListNode) + { + while (a != &Nil<T>ListNode) + { + <T>ListNode* n = new <T>ListNode; + n->ref = 1; + n->hd = a->hd; + r->tl = n; + r = n; + a = a->tl; + } + r->tl = &Nil<T>ListNode; + return <T>List(h); + } + else if ((*f)(a->hd, b->hd) <= 0) + { + <T>ListNode* n = new <T>ListNode; + n->ref = 1; + n->hd = a->hd; + r->tl = n; + r = n; + a = a->tl; + } + else + { + <T>ListNode* n = new <T>ListNode; + n->ref = 1; + n->hd = b->hd; + r->tl = n; + r = n; + b = b->tl; + } + } +} + +void <T>List::sort(<T>Comparator f) +{ + // strategy: place runs in queue, merge runs until done + // This is often very fast + + if (P == &Nil<T>ListNode || P->tl == &Nil<T>ListNode) + return; + + int qlen = 250; // guess a good queue size, realloc if necessary + + <T>ListNode** queue = (<T>ListNode**)malloc(qlen * sizeof(<T>ListNode*)); + + <T>ListNode* h = P; + <T>ListNode* a = h; + <T>ListNode* b = a->tl; + int qin = 0; + + while (b != &Nil<T>ListNode) + { + 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 = (<T>ListNode**)realloc(queue, qlen * sizeof(<T>ListNode*)); + } + queue[qin++] = h; + a->tl = &Nil<T>ListNode; + 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 == &Nil<T>ListNode) + { + h->tl = b; + break; + } + else if (b == &Nil<T>ListNode) + { + 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 <T>List::list_length() +{ + <T>ListNode* fast = P; + if (fast == &Nil<T>ListNode) + return 0; + + <T>ListNode* slow = fast->tl; + if (slow == &Nil<T>ListNode) + return 1; + + fast = slow->tl; + int n = 2; + + for (;;) + { + if (fast == &Nil<T>ListNode) + return n; + else if (fast->tl == &Nil<T>ListNode) + return n+1; + else if (fast == slow) + return -1; + else + { + n += 2; + fast = fast->tl->tl; + slow = slow->tl; + } + } +} + +void <T>List::error(const char* msg) +{ + (*lib_error_handler)("List", msg); +} + +int <T>List::OK() +{ + int v = P != 0; // have a node + // check that all nodes OK, even if circular: + + <T>ListNode* fast = P; + if (fast != &Nil<T>ListNode) + { + v &= fast->ref != 0; + <T>ListNode* slow = fast->tl; + v &= slow->ref != 0; + if (v && slow != &Nil<T>ListNode) + { + fast = slow->tl; + v &= fast->ref != 0; + while (v) + { + if (fast == &Nil<T>ListNode) + break; + else if (fast->tl == &Nil<T>ListNode) + 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; +} diff --git a/gnu/lib/libg++/g++-include/gen/List.hP b/gnu/lib/libg++/g++-include/gen/List.hP new file mode 100644 index 00000000000..cade890d04b --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/List.hP @@ -0,0 +1,279 @@ +// 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 _<T>List_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>List_h 1 + +#ifndef _<T>_typedefs +#define _<T>_typedefs 1 +typedef void (*<T>Procedure)(<T&>); +typedef <T> (*<T>Mapper)(<T&>); +typedef <T> (*<T>Combiner)(<T&>, <T&>); +typedef int (*<T>Predicate)(<T&>); +typedef int (*<T>Comparator)(<T&>, <T&>); +#endif + +#include <Pix.h> + +struct <T>ListNode +{ + <T>ListNode* tl; + short ref; + <T> hd; +}; + +extern <T>ListNode Nil<T>ListNode; + +class <T>List +{ +protected: + <T>ListNode* P; + + <T>List(<T>ListNode* p); +public: + <T>List(); + <T>List(<T&> head); + <T>List(<T&> head, <T>List& tl); + <T>List(<T>List& a); + <T>List(Pix p); + ~<T>List(); + + <T>List& operator = (<T>List& a); + + int null(); + int valid(); + operator const void* (); + int operator ! (); + + int length(); + int list_length(); + + <T>& get(); + <T>& head(); + <T>& operator [] (int n); + + <T>List nth(int n); + <T>List tail(); + <T>List last(); + + <T>List find(<T&> targ); + <T>List find(<T>List& targ); + int contains(<T&> targ); + int contains(<T>List& targ); + int position(<T&> targ); + + friend <T>List copy(<T>List& a); + friend <T>List concat(<T>List& a, <T>List& b); + friend <T>List append(<T>List& a, <T>List& b); + friend <T>List map(<T>Mapper f, <T>List& a); + friend <T>List merge(<T>List& a, <T>List& b, <T>Comparator f); + friend <T>List combine(<T>Combiner f, <T>List& a, <T>List& b); + friend <T>List reverse(<T>List& a); + friend <T>List select(<T>Predicate f, <T>List& a); + friend <T>List remove(<T&> targ, <T>List& a); + friend <T>List remove(<T>Predicate f, <T>List& a); + friend <T>List subst(<T&> old, <T&> repl, <T>List& a); + + void push(<T&> x); + <T> pop(); + + void set_tail(<T>List& p); + void append(<T>List& p); + void prepend(<T>List& p); + void del(<T&> targ); + void del(<T>Predicate f); + void select(<T>Predicate f); + void subst(<T&> old, <T&> repl); + void reverse(); + void sort(<T>Comparator f); + + void apply(<T>Procedure f); + <T> reduce(<T>Combiner f, <T&> base); + + friend int operator == (<T>List& a, <T>List& b); + friend int operator != (<T>List& a, <T>List& b); + + Pix first(); + void next(Pix& p); + Pix seek(<T&> item); + <T>& operator () (Pix p); + int owns(Pix p); + + void error(const char*); + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline void reference(<T>ListNode* p) +{ + if (p->ref >= 0) ++p->ref; +} + +inline void dereference(<T>ListNode* p) +{ + while (p->ref > 0 && --p->ref == 0) + { + <T>ListNode* n = p->tl; + delete(p); + p = n; + } +} + + +inline <T>ListNode* new<T>ListNode(<T&> h) +{ + <T>ListNode* p = new <T>ListNode; + p->ref = 1; + p->hd = h; + return p; +} + +inline <T>ListNode* new<T>ListNode(<T&> h, <T>ListNode* t) +{ + <T>ListNode* p = new <T>ListNode; + p->ref = 1; + p->hd = h; + p->tl = t; + return p; +} + + +inline <T>List::~<T>List() +{ + dereference(P); +} + +inline <T>List::<T>List() +{ + P = &Nil<T>ListNode; +} + +inline <T>List::<T>List(<T>ListNode* p) +{ + P = p; +} + +inline <T>List::<T>List(<T&> head) +{ + P = new<T>ListNode(head); + P->tl = &Nil<T>ListNode; +} + +inline <T>List::<T>List(<T&> head, <T>List& tl) +{ + P = new<T>ListNode(head, tl.P); + reference(P->tl); +} + +inline <T>List::<T>List(<T>List& a) +{ + reference(a.P); + P = a.P; +} + + +inline <T>& <T>List::get() +{ + return P->hd; +} + +inline <T>& <T>List::head() +{ + return P->hd; +} + + +inline <T>List <T>List::tail() +{ + reference(P->tl); + return <T>List(P->tl); +} + + + +inline int <T>List::null() +{ + return P == &Nil<T>ListNode; +} + +inline int <T>List::valid() +{ + return P != &Nil<T>ListNode; +} + +inline <T>List::operator const void* () +{ + return (P == &Nil<T>ListNode)? 0 : this; +} + +inline int <T>List::operator ! () +{ + return (P == &Nil<T>ListNode); +} + + +inline void <T>List::push(<T&> head) +{ + <T>ListNode* oldp = P; + P = new<T>ListNode(head, oldp); +} + + +inline int operator != (<T>List& x, <T>List& y) +{ + return !(x == y); +} + +inline Pix <T>List::first() +{ + return (P == &Nil<T>ListNode)? 0 : Pix(P); +} + +inline <T>& <T>List::operator () (Pix p) +{ + return ((<T>ListNode*)p)->hd; +} + +inline void <T>List::next(Pix& p) +{ + if (p != 0) + { + p = Pix(((<T>ListNode*)p)->tl); + if (p == &Nil<T>ListNode) p = 0; + } +} + +inline <T>List::<T>List(Pix p) +{ + P = (<T>ListNode*)p; + reference(P); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/MPlex.ccP b/gnu/lib/libg++/g++-include/gen/MPlex.ccP new file mode 100644 index 00000000000..2008d8555a5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/MPlex.ccP @@ -0,0 +1,850 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.MPlex.h" + +// <T>MChunk support + + +<T>MChunk::<T>MChunk(<T>* d, + int baseidx, + int lowidx, + int fenceidx, + int topidx) + : <T>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 <T>MChunk:: shrink_high () +{ + if (fence <= low) empty_error(); + --fence; + if (!valid(fence)) + --unused; + else + free(fence); + reset_high(); +} + +void <T>MChunk:: shrink_low () +{ + if (fence <= low) empty_error(); + if (!valid(low)) + --unused; + else + free(low); + ++low; + reset_low(); +} + +void <T>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 <T>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 <T>MChunk::del(int idx) +{ + if (idx < low || idx >= fence) index_error(); + int v = valid(idx); + if (v) + { + free(idx); + ++unused; + } + return v; +} + + +int <T>MChunk::undel(int idx) +{ + if (idx < low || idx >= fence) index_error(); + int v = valid(idx); + if (!v) + { + mark(idx); + --unused; + } + return v; +} + +int <T>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 <T>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 <T>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 <T>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 &= ((<T>MChunk*)(nxt->prev())) == this; // and links are OK + v &= ((<T>MChunk*)(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); +} + +<T>* <T>MChunk::succ(<T>* p) const +{ + int i = ((int) p - (int) data) / sizeof(<T>) + base + 1; + if (p == 0 || i < low) return 0; + while (i < fence && !valid(i)) ++i; + if (i >= fence) return 0; + return pointer_to(i); +} + +<T>* <T>MChunk::pred(<T>* p) const +{ + int i = ((int) p - (int) data) / sizeof(<T>) + base - 1; + if (p == 0 || i >= fence) return 0; + while (i >= low && !valid(i)) --i; + if (i < low) return 0; + return pointer_to(i); +} + +<T>* <T>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); +} + +<T>* <T>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); +} + +<T>MPlex:: <T>MPlex() +{ + unused = 0; + lo = fnc = 0; + csize = DEFAULT_INITIAL_CAPACITY; + <T>* data = new <T>[csize]; + hd = ch = new <T>MChunk(data, lo, lo, fnc, lo+csize); +} + +<T>MPlex:: <T>MPlex(int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + unused = 0; + lo = fnc = 0; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + hd = ch = new <T>MChunk(data, lo, lo, fnc, csize); + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + hd = ch = new <T>MChunk(data, chunksize, lo, fnc, fnc); + } +} + + +<T>MPlex:: <T>MPlex(int l, int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + unused = 0; + lo = fnc = l; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + hd = ch = new <T>MChunk(data, lo, lo, fnc, csize+lo); + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + hd = ch = new <T>MChunk(data, chunksize+lo, lo, fnc, fnc); + } +} + + +void <T>MPlex::make_initial_chunks(int up) +{ + int need = fnc - lo; + hd = 0; + if (up) + { + int l = lo; + do + { + int sz; + if (need >= csize) + sz = csize; + else + sz = need; + <T>* data = new <T> [csize]; + <T>MChunk* h = new <T>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; + <T>* data = new <T> [csize]; + <T>MChunk* h = new <T>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 = (<T>MChunk*) hd; +} + +<T>MPlex:: <T>MPlex(int l, int hi, const <T&> initval, int chunksize) +{ + 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); + } + unused = fnc - lo; + for (int i=lo; i<fnc; ++i) + undel_index(i); + fill(initval); +} + +<T>MPlex::<T>MPlex(const <T>MPlex& a) +{ + lo = a.lo; + fnc = a.fnc; + csize = a.csize; + unused = fnc - lo; + hd = 0; + const <T>IChunk* p = a.hd; + do + { + <T>* data = new <T> [p->size()]; + <T>MChunk* h = new <T>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 = (<T>MChunk*) hd; + for (int i = a.low(); i < a.fence(); a.next(i)) + { + undel_index(i); + (*this)[i] = a[i]; + } +} + +void <T>MPlex::operator= (const <T>MPlex& a) +{ + if (&a != this) + { + invalidate(); + lo = a.lo; + fnc = a.fnc; + csize = a.csize; + unused = fnc - lo; + hd = 0; + const <T>IChunk* p = a.hd; + do + { + <T>* data = new <T> [p->size()]; + <T>MChunk* h = new <T>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 = (<T>MChunk*) hd; + for (int i = a.low(); i < a.fence(); a.next(i)) + { + undel_index(i); + (*this)[i] = a[i]; + } + } +} + +int <T>MPlex::valid(int idx) const +{ + const <T>MChunk* tail = (<T>MChunk*)tl(); + const <T>MChunk* t = ch; + while (idx >= t->fence_index()) + { + if (t == tail) return 0; + t = ((<T>MChunk*)(t->next())); + } + while (idx < t->low_index()) + { + if (t == (<T>MChunk*)(hd)) return 0; + t = ((<T>MChunk*)(t->prev())); + } + set_cache(t); + return t-><T>MChunk::valid_index(idx); +} + +void <T>MPlex::cache(int idx) const +{ + const <T>MChunk* tail = (<T>MChunk*)tl(); + const <T>MChunk* t = ch; + while (idx >= t->fence_index()) + { + if (t == tail) index_error(); + t = ((<T>MChunk*)(t->next())); + } + while (idx < t->low_index()) + { + if (t == (<T>MChunk*)hd) index_error(); + t = ((<T>MChunk*)(t->prev())); + } + if (!t-><T>MChunk::valid_index(idx)) index_error(); + set_cache(t); +} + +void <T>MPlex::cache(const <T>* p) const +{ + const <T>MChunk* old = ch; + const <T>MChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = ((<T>MChunk*)(t->next())); + if (t == old) index_error(); + } + if (!t-><T>MChunk::valid_pointer(p)) index_error(); + set_cache(t); +} + +int <T>MPlex::owns(Pix px) const +{ + <T>* p = (<T>*)px; + const <T>MChunk* old = ch; + const <T>MChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = ((<T>MChunk*)(t->next())); + if (t == old) return 0; + } + set_cache(t); + return t-><T>MChunk::valid_pointer(p); +} + +int <T>MPlex::add_high(const <T&> elem) +{ + <T>MChunk* t = ((<T>MChunk*) tl()); + + if (!t->can_grow_high()) + { + <T>* data = new <T> [csize]; + t = (new <T>MChunk(data, fnc,fnc,fnc,fnc+csize)); + t->link_to_prev(tl()); + } + + *((t-><T>MChunk::grow_high())) = elem; + set_cache(t); + return fnc++; +} + +int <T>MPlex::add_low (const <T&> elem) +{ + <T>MChunk* t = ((<T>MChunk*) hd); + if (!t->can_grow_low()) + { + <T>* data = new <T> [csize]; + hd = new <T>MChunk(data, lo-csize, lo, lo, lo); + hd->link_to_next(t); + t = ((<T>MChunk*) hd); + } + + *((t-><T>MChunk::grow_low())) = elem; + set_cache(t); + return --lo; +} + +void <T>MPlex::adjust_bounds() +{ + <T>MChunk* t = ((<T>MChunk*) tl()); + + // clean up tail + + t->reset_high(); + while (t-><T>MChunk::empty() && !one_chunk()) + { + <T>MChunk* pred = (<T>MChunk*)(t->prev()); + del_chunk(t); + pred->reset_high(); + t = (pred); + } + if (one_chunk()) + t->reset_high(); + + int oldfnc = fnc; + fnc = t->fence_index(); + unused -= oldfnc - fnc; + + // and head.. + t = ((<T>MChunk*) hd); + t->reset_low(); + while (t-><T>MChunk::empty() && !one_chunk()) + { + hd = (<T>MChunk*)(t->next()); + del_chunk(t); + t = ((<T>MChunk*) hd); + t->reset_low(); + } + + int oldlo = lo; + lo = t->low_index(); + unused -= lo - oldlo; + + + set_cache(t); +} + +int <T>MPlex::del_high () +{ + if (empty()) empty_error(); + <T>MChunk* t = ((<T>MChunk*) tl()); + while (t-><T>MChunk::empty() && !one_chunk()) // possible stragglers + { + <T>MChunk* pred = (<T>MChunk*)(t->prev()); + del_chunk(t); + pred->reset_high(); + t = (pred); + } + t-><T>MChunk::shrink_high(); + while (t-><T>MChunk::empty() && !one_chunk()) + { + <T>MChunk* pred = (<T>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 <T>MPlex::del_low () +{ + if (empty()) empty_error(); + <T>MChunk* t = ((<T>MChunk*) hd); + while (t-><T>MChunk::empty() && !one_chunk()) + { + hd = (<T>MChunk*)(t->next()); + del_chunk(t); + t = ((<T>MChunk*) hd); + t->reset_low(); + } + t-><T>MChunk::shrink_low(); + while (t-><T>MChunk::empty() && !one_chunk()) + { + hd = (<T>MChunk*)(t->next()); + del_chunk(t); + t = ((<T>MChunk*) hd); + t->reset_low(); + } + int oldlo = lo; + lo = t->low_index(); + unused -= lo - oldlo - 1; + set_cache(t); + return lo; +} + +int <T>MPlex::add(const <T&> elem) +{ + if (unused == 0) + return add_high(elem); + + for(<T>MChunk* t = ch; + t->unused_indices() == 0; + t = (<T>MChunk*)(t->prev())) + ; + + int i = t->unused_index(); + set_cache(t); + undel_index(i); + (*this)[i] = elem; + return i; +} + +int <T>MPlex::unused_index() const +{ + if (unused == 0) index_error(); + + for(<T>MChunk* t = ch; + t->unused_indices() == 0; + t = (<T>MChunk*)(t->prev())) + ; + + set_cache(t); + return t->unused_index(); +} + +Pix <T>MPlex::unused_Pix() const +{ + if (unused == 0) return 0; + + for(<T>MChunk* t = ch; + t->unused_indices() == 0; + t = (<T>MChunk*)(t->prev())) + ; + + set_cache(t); + return t->pointer_to(t->unused_index()); +} + +int <T>MPlex::del_index(int idx) +{ + if (idx < lo || idx >= fnc) index_error(); + if (<T>MPlex::valid(idx)) + { + ++unused; + ch-><T>MChunk::del(idx); + return 1; + } + else + return 0; +} + +int <T>MPlex::dopred(int idx) const +{ + + if (idx >= fnc) idx = fnc; + if (idx <= lo) return lo - 1; + + const <T>MChunk* t = ch; + + while (idx > t->fence_index()) + { + t = ((<T>MChunk*)(t->next())); + } + while (idx <= t->low_index()) + { + t = ((<T>MChunk*)(t->prev())); + } + int i = t-><T>MChunk::pred(idx); + while (i < t->low_index() && i >= lo) + { + t = ((<T>MChunk*)(t->prev())); + i = t-><T>MChunk::last_index(); + } + set_cache(t); + return i; +} + + +int <T>MPlex::dosucc(int idx) const +{ + if (idx < lo) idx = lo; + if (idx >= fnc - 1) return fnc; + + const <T>MChunk* t = ch; + while (idx >= t->fence_index()) + { + t = ((<T>MChunk*)(t->next())); + } + while (idx < t->low_index()) + { + t = ((<T>MChunk*)(t->prev())); + } + int i = t-><T>MChunk::succ(idx); + while (i >= t->fence_index() && i < fnc) + { + t = (<T>MChunk*)(t->next()); + i = t-><T>MChunk::first_index(); + } + set_cache(t); + return i; +} + +void <T>MPlex::prev(Pix& i) const +{ + if (i == 0) return; + + <T>* p = (<T>*) i; + const <T>MChunk* old = ch; + const <T>MChunk* t = ch; + + while (!t->actual_pointer(p)) + { + t = ((<T>MChunk*)(t->prev())); + if (t == old) + { + i = 0; + return; + } + } + <T>* q = t-><T>MChunk::pred(p); + while (q == 0 && t != (<T>MChunk*)hd) + { + t = ((<T>MChunk*)(t->prev())); + q = t-><T>MChunk::last_pointer(); + } + + i = Pix(q); + set_cache(t); + return; +} + +void <T>MPlex::next(Pix& i) const +{ + if (i == 0) return; + + <T>* p = (<T>*) i; + const <T>MChunk* tail = (<T>MChunk*)(tl()); + const <T>MChunk* old = ch; + const <T>MChunk* t = ch; + + while (!t->actual_pointer(p)) + { + t = ((<T>MChunk*)(t->next())); + if (t == old) + { + i = 0; + return; + } + } + <T>* q = t-><T>MChunk::succ(p); + while (q == 0 && t != tail) + { + t = ((<T>MChunk*)(t->next())); + q = t-><T>MChunk::first_pointer(); + } + + i = Pix(q); + set_cache(t); + return; +} + + +void <T>MPlex::undel_index(int idx) +{ + if (idx < lo || idx >= fnc) index_error(); + + <T>MChunk* t = ch; + while (idx >= t->fence_index()) + { + t = ((<T>MChunk*)(t->next())); + } + while (idx < t->low_index()) + { + t = ((<T>MChunk*)(t->prev())); + } + int was_present = t-><T>MChunk::undel(idx); + if (!was_present) + { + --unused; + } + set_cache(t); + return; +} + +void <T>MPlex::clear() +{ + if (fnc != lo) + { + <T>MChunk* t = ((<T>MChunk*)tl()); + while (t != hd) + { + <T>MChunk* prv = (<T>MChunk*)(t->prev()); + del_chunk(t); + t = prv; + } + t-><T>MChunk::clear(lo); + set_cache(t); + fnc = lo; + unused = 0; + } +} + +int <T>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 <T>MChunk* t = (<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-><T>MChunk::OK(); // each chunk is OK + count += t->unused_indices(); + if (t == (<T>MChunk*)(tl())) + break; + else // and has indices less than succ + { + gap = t->next()->base_index() - t->top_index(); + v &= gap == 0; + count += gap; + + if (t != (<T>MChunk*)hd) // internal chunks can't grow + v &= !t->can_grow_low() && !t->can_grow_high(); + + t = (const <T>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; +} + diff --git a/gnu/lib/libg++/g++-include/gen/MPlex.hP b/gnu/lib/libg++/g++-include/gen/MPlex.hP new file mode 100644 index 00000000000..83e28637435 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/MPlex.hP @@ -0,0 +1,422 @@ +// 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 _<T>MPlex_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>MPlex_h 1 + + +#include "<T>.Plex.h" + + +// Number of bits per long, used in MChunk bit map operations + +#define _MAP_BITS 32 + + +class <T>MChunk : public <T>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: + + <T>MChunk(<T>* d, // ptr to array of elements + int base_idx, // initial indices + int low_idx, // & initially clear map + int fence_idx, + int top_idx); + + ~<T>MChunk(); + +// virtuals + + int first_index() const; + int last_index() const; + int succ(int idx) const; + int pred(int idx) const; + <T>* first_pointer() const; + <T>* last_pointer() const; + <T>* succ(<T>*) const; + <T>* pred(<T>*) const; + int empty() const; + int full() const; + int valid_index(int i) const; + int valid_pointer(const <T>* p) const; + <T>* grow_high (); + <T>* 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 <T>MPlex: public <T>Plex +{ + <T>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 <T>* p) const; + int dopred(int) const; + int dosucc(int) const; + + void set_cache(const <T>MChunk* t) const; // logically, + // not physically const + +public: + <T>MPlex(); // set low = 0; + // fence = 0; + // csize = default + + <T>MPlex(int ch_size); // low = 0; + // fence = 0; + // csize = ch_size + + <T>MPlex(int lo, // low = lo; + int ch_size); // fence=lo + // csize = ch_size + + <T>MPlex(int lo, // low = lo + int hi, // fence = hi+1 + const <T&> initval,// fill with initval, + int ch_size = 0); // csize= ch_size + // or fence-lo if 0 + + <T>MPlex(const <T>MPlex&); + + void operator= (const <T>MPlex&); + +// virtuals + + <T>& high_element (); + <T>& low_element (); + const <T>& high_element () const; + const <T>& low_element () const; + + Pix first() const; + Pix last() const ; + void prev(Pix& ptr) const; + void next(Pix& ptr) const; + int owns(Pix p) const; + <T>& operator () (Pix p); + const <T>& 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; + <T>& operator [] (int index); + const <T>& 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 <T&> elem); + int del_high (); + int add_low (const <T&> 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 <T&> elem); // add anywhere +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>MChunk:: ~<T>MChunk() +{ + delete map; +} + +inline void <T>MChunk::mark(int idx) +{ + unsigned int i = idx - base; + map[i / _MAP_BITS] |= 1 << (i & (_MAP_BITS - 1)); +} + +inline void <T>MChunk::free(int idx) +{ + unsigned int i = idx - base; + map[i / _MAP_BITS] &= ~(1 << (i & (_MAP_BITS - 1))); +} + +inline int <T>MChunk::valid(int idx) const +{ + unsigned int i = idx - base; + return map[i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1))); +} + +inline int <T>MChunk:: valid_index(int i) const +{ + return i >= low && i < fence && valid(i); +} + +inline int <T>MChunk:: valid_pointer(const <T>* p) const +{ + int i = ((int)p - (int)data) / sizeof(<T>); + return i >= 0 && i < (fence - base) && + (map[(unsigned)i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1)))); +} + +inline int <T>MChunk::empty() const +{ + return fence - low - unused == 0; +} + +inline int <T>MChunk::full() const +{ + return unused + (top - fence) + (low - base) == 0; +} + +inline int <T>MChunk::succ(int idx) const +{ + int i = (idx < low)? low : idx + 1; + while (i < fence && !valid(i)) ++i; + return i; +} + +inline int <T>MChunk::pred(int idx) const +{ + int i = (idx > fence)? (fence - 1) : idx - 1; + while (i >= low && !valid(i)) --i; + return i; +} + +inline int <T>MChunk::unused_indices() const +{ + return unused; +} + +inline <T>* <T>MChunk:: grow_high () +{ + if (!can_grow_high()) full_error(); + mark(fence); + return &(data[fence++ - base]); +} + +inline <T>* <T>MChunk:: grow_low () +{ + if (!can_grow_low()) full_error(); + mark(--low); + return &(data[low - base]); +} + +inline void <T>MChunk::reset_low() +{ + while (low < fence && !valid(low)) + { + --unused; + ++low; + } +} + +inline void <T>MChunk::reset_high() +{ + while (fence > low && !valid(fence - 1)) + { + --unused; + --fence; + } +} + +inline int <T>MPlex::full () const +{ + return 0; +} + +inline int <T>MPlex::can_add_high() const +{ + return 1; +} + +inline int <T>MPlex::can_add_low() const +{ + return 1; +} + +inline int <T>MPlex::available() const +{ + return unused; +} + +inline int <T>MPlex::count() const +{ + return fnc - lo - unused; +} + +inline void <T>MPlex::set_cache(const <T>MChunk* t) const +{ + ((<T>MPlex*)(this))->ch = (<T>MChunk*)t; +} + +inline <T>& <T>MPlex:: operator [] (int idx) +{ + if (!ch-><T>MChunk::valid_index(idx)) cache(idx); + return * (ch->pointer_to(idx)); +} + +inline const <T>& <T>MPlex:: operator [] (int idx) const +{ + if (!ch-><T>MChunk::valid_index(idx)) cache(idx); + return * ((const <T>*)(ch->pointer_to(idx))); +} + +inline int <T>MPlex::Pix_to_index(Pix p) const +{ + if (!ch-><T>MChunk::valid_pointer((<T>*)p)) cache((<T>*)p); + return ch->index_of((<T>*)p); +} + +inline int <T>MPlex::high() const +{ + return (((const <T>MChunk*)tl())-><T>MChunk::valid_index(fnc-1)) ? + fnc-1 : dopred(fnc-1); +} + +inline int <T>MPlex::low() const +{ + return (((const <T>MChunk*)hd)-><T>MChunk::valid_index(lo))? lo : dosucc(lo); +} + +inline <T>& <T>MPlex::low_element () +{ + return (*this)[low()]; +} + +inline const <T>& <T>MPlex::low_element () const +{ + return (*this)[low()]; +} + +inline <T>& <T>MPlex::high_element () +{ + return (*this)[high()]; +} + +inline const <T>& <T>MPlex::high_element () const +{ + return (*this)[high()]; +} + +inline Pix <T>MPlex::index_to_Pix(int idx) const +{ + if (!ch-><T>MChunk::valid_index(idx)) cache(idx); + return Pix(ch->pointer_to(idx)); +} + +inline void <T>MPlex::next(int& idx) const +{ + idx = (ch-><T>MChunk::valid_index(idx+1))? idx+1 : dosucc(idx); +} + +inline void <T>MPlex::prev(int& idx) const +{ + idx = (ch-><T>MChunk::valid_index(idx-1))? idx-1 : dopred(idx); +} + +inline Pix <T>MPlex::first() const +{ + return index_to_Pix(low()); +} + +inline Pix <T>MPlex::last() const +{ + return index_to_Pix(high()); +} + + +inline void <T>MPlex::undel_Pix(Pix p) +{ + undel_index(Pix_to_index(p)); +} + +inline int <T>MPlex::del_Pix(Pix p) +{ + return del_index(Pix_to_index(p)); +} + +inline <T>& <T>MPlex:: operator () (Pix p) +{ + return *((<T>*)p); +} + +inline const <T>& <T>MPlex:: operator () (Pix p) const +{ + return *((const <T>*)p); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Map.ccP b/gnu/lib/libg++/g++-include/gen/Map.ccP new file mode 100644 index 00000000000..4bf254160f0 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Map.ccP @@ -0,0 +1,63 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include "<T>.<C>.Map.h" + + +Pix <T><C>Map::seek(<T&> item) +{ + for (Pix i = first(); i != 0 && !(<T>EQ(key(i), item)); next(i)); + return i; +} + +int <T><C>Map::owns(Pix idx) +{ + if (idx == 0) return 0; + for (Pix i = first(); i; next(i)) if (i == idx) return 1; + return 0; +} + +void <T><C>Map::clear() +{ + Pix i = first(); + while (i != 0) + { + del(key(i)); + i = first(); + } +} + +int <T><C>Map::contains (<T&> item) +{ + return seek(item) != 0; +} + + +void <T><C>Map::error(const char* msg) +{ + (*lib_error_handler)("Map", msg); +} diff --git a/gnu/lib/libg++/g++-include/gen/Map.hP b/gnu/lib/libg++/g++-include/gen/Map.hP new file mode 100644 index 00000000000..301a4ab8094 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Map.hP @@ -0,0 +1,96 @@ +// 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 _<T><C>Map_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>Map_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +class <T><C>Map +{ +protected: + int count; + <C> def; + +public: + <T><C>Map(<C&> dflt); + virtual ~<T><C>Map(); + + int length(); // current number of items + int empty(); + + virtual int contains(<T&> key); // is key mapped? + + virtual void clear(); // delete all items + + virtual <C>& operator [] (<T&> key) = 0; // access contents by key + + virtual void del(<T&> 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 <T>& key(Pix i) = 0; // access key at i + virtual <C>& contents(Pix i) = 0; // access contents at i + + virtual int owns(Pix i); // is i a valid Pix ? + virtual Pix seek(<T&> key); // Pix of key + + <C>& dflt(); // access default val + + void error(const char* msg); + virtual int OK() = 0; // rep invariant +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>Map::~<T><C>Map() {} + +inline int <T><C>Map::length() +{ + return count; +} + +inline int <T><C>Map::empty() +{ + return count == 0; +} + +inline <C>& <T><C>Map::dflt() +{ + return def; +} + +inline <T><C>Map::<T><C>Map(<C&> dflt) :def(dflt) +{ + count = 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/OSLBag.ccP b/gnu/lib/libg++/g++-include/gen/OSLBag.ccP new file mode 100644 index 00000000000..79c95cbe515 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OSLBag.ccP @@ -0,0 +1,201 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.OSLBag.h" + + +Pix <T>OSLBag::seek(<T&> item, Pix i) +{ + if (i == 0) i = p.first(); else next(i); + for (; i != 0; p.next(i)) + { + int cmp = <T>CMP(item, p(i)); + if (cmp == 0) + return i; + else if (cmp < 0) + return 0; + } + return 0; +} + +int <T>OSLBag::nof(<T&> item) +{ + int n = 0; + for (Pix i = p.first(); i != 0; p.next(i)) + { + int cmp = <T>CMP(item, p(i)); + if (cmp == 0) + ++n; + else if (cmp < 0) + break; + } + return n; +} + +Pix <T>OSLBag::add(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + { + ++count; + return p.prepend(item); + } + int cmp = <T>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 = <T>CMP(item, p(i)); + if (cmp <= 0) + { + ++count; + return p.ins_after(trail, item); + } + else + { + trail = i; + p.next(i); + } + } + } +} + +void <T>OSLBag::del(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + return; + int cmp = <T>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 = <T>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 <T>OSLBag::remove(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + return; + int cmp = <T>CMP(item, p(i)); + if (cmp < 0) + return; + else if (cmp == 0) + { + do + { + --count; + p.del_front(); + i = p.first(); + } while (i != 0 && <T>EQ(item, p(i))); + } + else + { + Pix trail = i; + p.next(i); + while (i != 0) + { + cmp = <T>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 && <T>EQ(item, p(i))); + return; + } + else + { + trail = i; + p.next(i); + } + } + } +} + +int <T>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 &= <T>CMP(p(trail), p(i)) <= 0; + trail = i; + next(i); + } + } + if (!v) error("invariant failure"); + return v; +} + diff --git a/gnu/lib/libg++/g++-include/gen/OSLBag.hP b/gnu/lib/libg++/g++-include/gen/OSLBag.hP new file mode 100644 index 00000000000..36d74bcb9ee --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OSLBag.hP @@ -0,0 +1,100 @@ +// 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 _<T>OSLBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>OSLBag_h 1 + +#include "<T>.Bag.h" +#include "<T>.SLList.h" + +class <T>OSLBag : public <T>Bag +{ +protected: + <T>SLList p; + +public: + <T>OSLBag(); + <T>OSLBag(const <T>OSLBag&); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + + int contains(<T&> item); + int nof(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item, Pix from = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>OSLBag::<T>OSLBag() : p() { count = 0; } + +inline <T>OSLBag::<T>OSLBag(const <T>OSLBag& s) : p(s.p) { count = s.count; } + +inline Pix <T>OSLBag::first() +{ + return p.first(); +} + +inline void <T>OSLBag::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>OSLBag::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>OSLBag::clear() +{ + count = 0; p.clear(); +} + +inline int <T>OSLBag::owns (Pix idx) +{ + return p.owns(idx); +} + +inline int <T>OSLBag::contains(<T&> item) +{ + return seek(item) != 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/OSLSet.ccP b/gnu/lib/libg++/g++-include/gen/OSLSet.ccP new file mode 100644 index 00000000000..2ab19445a6a --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OSLSet.ccP @@ -0,0 +1,326 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.OSLSet.h" + + +Pix <T>OSLSet::seek(<T&> item) +{ + for (Pix i = p.first(); i != 0; p.next(i)) + { + int cmp = <T>CMP(item, p(i)); + if (cmp == 0) + return i; + else if (cmp < 0) + return 0; + } + return 0; +} + +Pix <T>OSLSet::add(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + { + ++count; + return p.prepend(item); + } + int cmp = <T>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 = <T>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 <T>OSLSet::del(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + return; + int cmp = <T>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 = <T>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 <T>OSLSet::operator <= (<T>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 = <T>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 <T>OSLSet::operator == (<T>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 (!<T>EQ(p(i),b.p(j))) return 0; + next(i); + b.next(j); + } + return 1; +} + + +void <T>OSLSet::operator |= (<T>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 = <T>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 <T>OSLSet::operator -= (<T>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 = <T>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 <T>OSLSet::operator &= (<T>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 = <T>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 <T>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 &= <T>CMP(p(trail), p(i)) < 0; + trail = i; + next(i); + } + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/OSLSet.hP b/gnu/lib/libg++/g++-include/gen/OSLSet.hP new file mode 100644 index 00000000000..1e94c09efc8 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OSLSet.hP @@ -0,0 +1,109 @@ +// 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 _<T>OSLSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>OSLSet_h 1 + +#include "<T>.Set.h" +#include "<T>.SLList.h" + +class <T>OSLSet : public <T>Set +{ +protected: + <T>SLList p; + +public: + <T>OSLSet(); + <T>OSLSet(const <T>OSLSet&); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + void operator |= (<T>OSLSet& b); + void operator -= (<T>OSLSet& b); + void operator &= (<T>OSLSet& b); + + int operator == (<T>OSLSet& b); + int operator != (<T>OSLSet& b); + int operator <= (<T>OSLSet& b); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>OSLSet::<T>OSLSet() : p() { count = 0; } + +inline <T>OSLSet::<T>OSLSet(const <T>OSLSet& s) : p(s.p) { count = s.count; } + +inline Pix <T>OSLSet::first() +{ + return p.first(); +} + +inline void <T>OSLSet::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>OSLSet::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>OSLSet::clear() +{ + count = 0; p.clear(); +} + +inline int <T>OSLSet::contains (<T&> item) +{ + return seek(item) != 0; +} + +inline int <T>OSLSet::owns (Pix idx) +{ + return p.owns(idx); +} + +inline int <T>OSLSet::operator != (<T>OSLSet& b) +{ + return !(*this == b); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/OXPBag.ccP b/gnu/lib/libg++/g++-include/gen/OXPBag.ccP new file mode 100644 index 00000000000..2a396441c01 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OXPBag.ccP @@ -0,0 +1,226 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.OXPBag.h" + + +Pix <T>OXPBag::seek(<T&> item, Pix i) +{ + if (i == 0) + { + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>CMP(item, p[mid]); + if (cmp == 0) + { + while (mid > p.low() && <T>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 = <T>CMP(item, p(i)); + if (cmp == 0) + { + next(i); + return (<T>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 = <T>CMP(item, p[mid]); + if (cmp == 0) + { + while (mid > ind && <T>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 <T>OXPBag::nof(<T&> item) +{ + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>CMP(item, p[mid]); + if (cmp == 0) + { + l = h = mid; + while (l > p.low() && <T>EQ(item, p[l - 1])) --l; + while (h < p.high() && <T>EQ(item, p[h + 1])) ++h; + return h - l + 1; + } + else if (cmp < 0) + h = mid - 1; + else + l = mid + 1; + } + return 0; +} + +Pix <T>OXPBag::add(<T&> 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 = <T>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 <T>OXPBag::del(<T&> item) +{ + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>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 <T>OXPBag::remove(<T&> item) +{ + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>CMP(item, p[mid]); + if (cmp == 0) + { + l = h = mid; + while (l > p.low() && <T>EQ(item, p[l - 1])) --l; + while (h < p.high() && <T>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 <T>OXPBag::OK() +{ + int v = p.OK(); + v &= count == p.length(); + for (int i = p.low(); i < p.high(); ++i) v &= <T>CMP(p[i], p[i+1]) <= 0; + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/OXPBag.hP b/gnu/lib/libg++/g++-include/gen/OXPBag.hP new file mode 100644 index 00000000000..5542a273dc3 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OXPBag.hP @@ -0,0 +1,76 @@ +#ifndef _<T>OXPBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>OXPBag_h 1 + +#include "<T>.Bag.h" +#include "<T>.XPlex.h" + +class <T>OXPBag : public <T>Bag +{ +protected: + <T>XPlex p; + +public: + <T>OXPBag(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>OXPBag(const <T>OXPBag&); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int nof(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item, Pix from = 0); + + int OK(); +}; + + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>OXPBag::<T>OXPBag(int chunksize) + : p(chunksize) { count = 0; } + +inline <T>OXPBag::<T>OXPBag(const <T>OXPBag& s) : p(s.p) { count = s.count; } + +inline Pix <T>OXPBag::first() +{ + return p.first(); +} + +inline void <T>OXPBag::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>OXPBag::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>OXPBag::clear() +{ + count = 0; p.clear(); +} + +inline int <T>OXPBag::owns (Pix idx) +{ + return p.owns(idx); +} + +inline int <T>OXPBag::contains(<T&> item) +{ + return seek(item) != 0; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/OXPSet.ccP b/gnu/lib/libg++/g++-include/gen/OXPSet.ccP new file mode 100644 index 00000000000..f7a99f8a86f --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OXPSet.ccP @@ -0,0 +1,285 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.OXPSet.h" + + +Pix <T>OXPSet::seek(<T&> item) +{ + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>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 <T>OXPSet::add(<T&> 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 = <T>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 <T>OXPSet::del(<T&> item) +{ + int l = p.low(); + int h = p.high(); + while (l <= h) + { + int mid = (l + h) / 2; + int cmp = <T>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 <T>OXPSet::operator <= (<T>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 = <T>CMP(p[i], b.p[j]); + if (cmp == 0) + { + ++i; ++j; + } + else if (cmp < 0) + return 0; + else + ++j; + } +} + +int <T>OXPSet::operator == (<T>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 (!<T>EQ(p[i++], b.p[j++])) return 0; + return 1; +} + + +void <T>OXPSet::operator |= (<T>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 = <T>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 <T>OXPSet::operator -= (<T>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 = <T>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 <T>OXPSet::operator &= (<T>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 = <T>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 <T>OXPSet::OK() +{ + int v = p.OK(); + v &= count == p.length(); + for (int i = p.low(); i < p.high(); ++i) v &= <T>CMP(p[i], p[i+1]) < 0; + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/OXPSet.hP b/gnu/lib/libg++/g++-include/gen/OXPSet.hP new file mode 100644 index 00000000000..fb1cb3c4fa2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/OXPSet.hP @@ -0,0 +1,110 @@ +// 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 _<T>OXPSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>OXPSet_h 1 + +#include "<T>.Set.h" +#include "<T>.XPlex.h" + +class <T>OXPSet : public <T>Set +{ +protected: + <T>XPlex p; + +public: + <T>OXPSet(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>OXPSet(const <T>OXPSet&); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + void operator |= (<T>OXPSet& b); + void operator -= (<T>OXPSet& b); + void operator &= (<T>OXPSet& b); + + int operator == (<T>OXPSet& b); + int operator != (<T>OXPSet& b); + int operator <= (<T>OXPSet& b); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>OXPSet::<T>OXPSet(int chunksize) + : p(chunksize) { count = 0; } + +inline <T>OXPSet::<T>OXPSet(const <T>OXPSet& s) : p(s.p) { count = s.count; } + +inline Pix <T>OXPSet::first() +{ + return p.first(); +} + +inline void <T>OXPSet::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>OXPSet::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>OXPSet::clear() +{ + count = 0; p.clear(); +} + +inline int <T>OXPSet::contains (<T&> item) +{ + return seek(item) != 0; +} + +inline int <T>OXPSet::owns (Pix idx) +{ + return p.owns(idx); +} + +inline int <T>OXPSet::operator != (<T>OXPSet& b) +{ + return !(*this == b); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/PHPQ.ccP b/gnu/lib/libg++/g++-include/gen/PHPQ.ccP new file mode 100644 index 00000000000..cc688732c35 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/PHPQ.ccP @@ -0,0 +1,342 @@ +// 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. +*/ + + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <values.h> +#include "<T>.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. +// +// + +<T>PHPQ::<T>PHPQ(int sz) +{ + storage = 0; + root = 0; + count = 0; + size = 0; + prealloc(sz); +} + +<T>PHPQ::<T>PHPQ(<T>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 <T>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 + <T>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 <T>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 + { + <T>PHPQNode* newstor = new <T>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 <T>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 <T>PHPQ::enq(<T&> 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 (<T>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 <T>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 (<T>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 <T>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 <T>PHPQ::seek(<T&> key) +{ + for (int i = 1; i < size; ++i) + if (storage[i].valid && <T>EQ(storage[i].item, key)) + return Pix(i); + return 0; +} + +Pix <T>PHPQ::first() +{ + for (int i = 1; i < size; ++i) + if (storage[i].valid) + return Pix(i); + return 0; +} + + +void <T>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 <T>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 <T>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; +} + + diff --git a/gnu/lib/libg++/g++-include/gen/PHPQ.hP b/gnu/lib/libg++/g++-include/gen/PHPQ.hP new file mode 100644 index 00000000000..acc6ebb2987 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/PHPQ.hP @@ -0,0 +1,118 @@ +// 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 <T>PHPQ_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define <T>PHPQ_h 1 + +#include "<T>.PQ.h" + +#ifndef <T>PHPQIndex +#define <T>PHPQIndex unsigned short +#endif + +struct <T>PHPQNode +{ + <T>PHPQIndex sibling; + <T>PHPQIndex children; + <T> item; + char valid; +}; + + +class <T>PHPQ : public <T>PQ +{ + <T>PHPQNode* storage; // table -- freelist in storage[0].sibling + int root; + int size; + + void prealloc(int); + int check_sibling_list(int, int); + +public: + + <T>PHPQ(int sz = DEFAULT_INITIAL_CAPACITY); + <T>PHPQ(<T>PHPQ&); + ~<T>PHPQ(); + + Pix enq(<T&> item); + <T> deq(); + + <T>& front(); + void del_front(); + + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + void del(Pix i); + Pix seek(<T&> item); + + int OK(); // rep invariant +}; + + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>PHPQ::~<T>PHPQ() +{ + delete [size] storage; +} + + +inline <T> <T>PHPQ::deq() +{ + if (count == 0) error("deq of empty PQ"); + <T> x = storage[root].item; + del_front(); + return x; +} + + +inline <T>& <T>PHPQ::front() +{ + if (count == 0) error("front of empty PQ"); + return storage[root].item; +} + +inline int <T>PHPQ::contains(<T&> item) +{ + return seek(item) != 0; +} + +inline <T>& <T>PHPQ::operator() (Pix p) +{ + if (p == 0) error("null Pix"); + return storage[int(p)].item; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/PQ.ccP b/gnu/lib/libg++/g++-include/gen/PQ.ccP new file mode 100644 index 00000000000..7aeddcbd2e9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/PQ.ccP @@ -0,0 +1,67 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include "<T>.PQ.h" + + + +<T> <T>PQ::deq() +{ + <T> x = front(); + del_front(); + return x; +} + +Pix <T>PQ::seek(<T&> item) +{ + for (Pix i = first(); i != 0 && !(<T>EQ((*this)(i), item)); next(i)); + return i; +} + +int <T>PQ::owns(Pix idx) +{ + if (idx == 0) return 0; + for (Pix i = first(); i; next(i)) if (i == idx) return 1; + return 0; +} + +void <T>PQ::clear() +{ + while (count != 0) del_front(); +} + +int <T>PQ::contains (<T&> item) +{ + return seek(item) != 0; +} + + +void <T>PQ::error(const char* msg) +{ + (*lib_error_handler)("PQ", msg); +} + diff --git a/gnu/lib/libg++/g++-include/gen/PQ.hP b/gnu/lib/libg++/g++-include/gen/PQ.hP new file mode 100644 index 00000000000..eb7b22cdf70 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/PQ.hP @@ -0,0 +1,80 @@ +// 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 _<T>PQ_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>PQ_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +class <T>PQ +{ +protected: + + int count; + +public: + int length(); // current number of items + int empty(); + + virtual Pix enq(<T&> item) = 0; // add item; return Pix + virtual <T> deq(); // return & remove min + + virtual <T>& front() = 0; // access min item + virtual void del_front() = 0; // delete min item + + virtual int contains(<T&> 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 <T>& 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(<T&> item); // Pix of item + + void error(const char* msg); + virtual int OK() = 0; // rep invariant +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline int <T>PQ::length() +{ + return count; +} + +inline int <T>PQ::empty() +{ + return count == 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Plex.ccP b/gnu/lib/libg++/g++-include/gen/Plex.ccP new file mode 100644 index 00000000000..9d475612de1 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Plex.ccP @@ -0,0 +1,227 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.Plex.h" + +// IChunk support + +volatile void <T>IChunk::error(const char* msg) const +{ + (*lib_error_handler)("<T>IChunk", msg); +} + +volatile void <T>IChunk::index_error() const +{ + error("attempt to use invalid index"); +} + +volatile void <T>IChunk::empty_error() const +{ + error("invalid use of empty chunk"); +} + +volatile void <T>IChunk::full_error() const +{ + error("attempt to extend chunk beyond bounds"); +} + +<T>IChunk:: ~<T>IChunk() {} + +<T>IChunk::<T>IChunk(<T>* 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 <T>IChunk:: re_index(int lo) +{ + int delta = lo - low; + base += delta; + low += delta; + fence += delta; + top += delta; +} + + +void <T>IChunk::clear(int lo) +{ + int s = top - base; + low = base = fence = lo; + top = base + s; +} + +void <T>IChunk::cleardown(int hi) +{ + int s = top - base; + low = top = fence = hi; + base = top - s; +} + +int <T>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 <T>Plex::error(const char* msg) const +{ + (*lib_error_handler)("Plex", msg); +} + +volatile void <T>Plex::index_error() const +{ + error("attempt to access invalid index"); +} + +volatile void <T>Plex::empty_error() const +{ + error("attempted operation on empty plex"); +} + +volatile void <T>Plex::full_error() const +{ + error("attempt to increase size of plex past limit"); +} + +// generic plex ops + +<T>Plex:: ~<T>Plex() +{ + invalidate(); +} + + +void <T>Plex::append (const <T>Plex& a) +{ + for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); +} + +void <T>Plex::prepend (const <T>Plex& a) +{ + for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); +} + +void <T>Plex::reverse() +{ + <T> 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 <T>Plex::fill(const <T&> x) +{ + for (int i = lo; i < fnc; ++i) (*this)[i] = x; +} + +void <T>Plex::fill(const <T&> x, int lo, int hi) +{ + for (int i = lo; i <= hi; ++i) (*this)[i] = x; +} + + +void <T>Plex::del_chunk(<T>IChunk* x) +{ + if (x != 0) + { + x->unlink(); + int sz = x->size(); + <T>* data = (<T>*)(x->invalidate()); + delete [sz] data; + delete x; + } +} + + +void <T>Plex::invalidate() +{ + <T>IChunk* t = hd; + if (t != 0) + { + <T>IChunk* tail = tl(); + while (t != tail) + { + <T>IChunk* nxt = t->next(); + del_chunk(t); + t = nxt; + } + del_chunk(t); + hd = 0; + } +} + +int <T>Plex::reset_low(int l) +{ + int old = lo; + int diff = l - lo; + if (diff != 0) + { + lo += diff; + fnc += diff; + <T>IChunk* t = hd; + do + { + t->re_index(t->low_index() + diff); + t = t->next(); + } while (t != hd); + } + return old; +} + + + + diff --git a/gnu/lib/libg++/g++-include/gen/Plex.hP b/gnu/lib/libg++/g++-include/gen/Plex.hP new file mode 100644 index 00000000000..38a1ef66673 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Plex.hP @@ -0,0 +1,503 @@ +// 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 _<T>Plex_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Plex_h 1 + +#include <std.h> +#include <Pix.h> +#include "<T>.defs.h" + +// Plexes are made out of <T>IChunks + +#include <stddef.h> + +class <T>IChunk +{ +//public: // kludge until C++ `protected' policies settled +protected: + + <T>* 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 + + <T>IChunk* nxt; // circular links + <T>IChunk* prv; + +public: + +// constructors + + <T>IChunk(<T>* d, // ptr to array of elements + int base_idx, // initial indices + int low_idx, + int fence_idx, + int top_idx); + + virtual ~<T>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 <T>* p) const; // same for ptr + int actual_pointer(const <T>* p) const; + virtual int valid_pointer(const <T>* p) const; + + <T>* pointer_to(int i) const ; // pointer to data indexed by i + // caution: i is not checked for validity + int index_of(const <T>* 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 <T>* first_pointer() const; // pointer to first valid pos or 0 + virtual <T>* last_pointer() const; // pointer to first valid pos or 0 + virtual <T>* succ(<T>* p) const; // next pointer or 0 + virtual <T>* pred(<T>* p) const; // previous pointer or 0 + +// modification + + virtual <T>* grow_high (); // return spot to add an element + virtual <T>* 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 + + <T>IChunk* next() const; + <T>IChunk* prev() const; + + void link_to_prev(<T>IChunk* prev); + void link_to_next(<T>IChunk* next); + void unlink(); + +// state checks + + <T>* 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; +}; + +// <T>Plex is a partly `abstract' class: few of the virtuals +// are implemented at the Plex level, only in the subclasses + +class <T>Plex +{ +protected: + + <T>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(<T>IChunk*); // delete a chunk + + <T>IChunk* tl() const; // last chunk; + int one_chunk() const; // true if hd == tl() + +public: + +// constructors, etc. + + <T>Plex(); // no-op + + virtual ~<T>Plex(); + + +// Access functions + + virtual <T>& operator [] (int idx) = 0; // access by index; + virtual <T>& operator () (Pix p) = 0; // access by Pix; + + virtual <T>& high_element () = 0; // access high element + virtual <T>& low_element () = 0; // access low element + +// read-only versions for const Plexes + + virtual const <T>& operator [] (int idx) const = 0; // access by index; + virtual const <T>& operator () (Pix p) const = 0; // access by Pix; + + virtual const <T>& high_element () const = 0; // access high element + virtual const <T>& 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 <T&> elem) =0;// add new element at high end + // return new high + + virtual int add_low(const <T&> 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 <T>::~<T> + + +// operations on multiple elements + + virtual void fill(const <T&> x); // set all elements = x + virtual void fill(const <T&> 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 <T>Plex& a); // concatenate a copy + virtual void prepend(const <T>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; +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +// <T>IChunk ops + +inline int <T>IChunk:: size() const +{ + return top - base; +} + + +inline int <T>IChunk:: base_index() const +{ + return base; +} + +inline int <T>IChunk:: low_index() const +{ + return low; +} + +inline int <T>IChunk:: fence_index() const +{ + return fence; +} + +inline int <T>IChunk:: top_index() const +{ + return top; +} + +inline <T>* <T>IChunk:: pointer_to(int i) const +{ + return &(data[i-base]); +} + +inline int <T>IChunk:: index_of(const <T>* p) const +{ + return ((int)p - (int)data) / sizeof(<T>) + base; +} + +inline int <T>IChunk:: possible_index(int i) const +{ + return i >= base && i < top; +} + +inline int <T>IChunk:: possible_pointer(const <T>* p) const +{ + return p >= data && p < &(data[top-base]); +} + +inline int <T>IChunk:: actual_index(int i) const +{ + return i >= low && i < fence; +} + +inline int <T>IChunk:: actual_pointer(const <T>* p) const +{ + return p >= data && p < &(data[fence-base]); +} + +inline int <T>IChunk:: can_grow_high () const +{ + return fence < top; +} + +inline int <T>IChunk:: can_grow_low () const +{ + return base < low; +} + +inline <T>* <T>IChunk:: invalidate() +{ + <T>* p = data; + data = 0; + return p; +} + + +inline <T>IChunk* <T>IChunk::prev() const +{ + return prv; +} + +inline <T>IChunk* <T>IChunk::next() const +{ + return nxt; +} + +inline void <T>IChunk::link_to_prev(<T>IChunk* prev) +{ + nxt = prev->nxt; + prv = prev; + nxt->prv = this; + prv->nxt = this; +} + +inline void <T>IChunk::link_to_next(<T>IChunk* next) +{ + prv = next->prv; + nxt = next; + nxt->prv = this; + prv->nxt = this; +} + +inline void <T>IChunk::unlink() +{ + <T>IChunk* n = nxt; + <T>IChunk* p = prv; + n->prv = p; + p->nxt = n; + prv = nxt = this; +} + +inline int <T>IChunk:: empty() const +{ + return low == fence; +} + +inline int <T>IChunk:: full() const +{ + return top - base == fence - low; +} + +inline int <T>IChunk:: first_index() const +{ + return (low == fence)? fence : low; +} + +inline int <T>IChunk:: last_index() const +{ + return (low == fence)? low - 1 : fence - 1; +} + +inline int <T>IChunk:: succ(int i) const +{ + return (i < low) ? low : i + 1; +} + +inline int <T>IChunk:: pred(int i) const +{ + return (i > fence) ? (fence - 1) : i - 1; +} + +inline int <T>IChunk:: valid_index(int i) const +{ + return i >= low && i < fence; +} + +inline int <T>IChunk:: valid_pointer(const <T>* p) const +{ + return p >= &(data[low - base]) && p < &(data[fence - base]); +} + +inline <T>* <T>IChunk:: grow_high () +{ + if (!can_grow_high()) full_error(); + return &(data[fence++ - base]); +} + +inline <T>* <T>IChunk:: grow_low () +{ + if (!can_grow_low()) full_error(); + return &(data[--low - base]); +} + +inline void <T>IChunk:: shrink_high () +{ + if (empty()) empty_error(); + --fence; +} + +inline void <T>IChunk:: shrink_low () +{ + if (empty()) empty_error(); + ++low; +} + +inline <T>* <T>IChunk::first_pointer() const +{ + return (low == fence)? 0 : &(data[low - base]); +} + +inline <T>* <T>IChunk::last_pointer() const +{ + return (low == fence)? 0 : &(data[fence - base - 1]); +} + +inline <T>* <T>IChunk::succ(<T>* p) const +{ + return ((p+1) < &(data[low - base]) || (p+1) >= &(data[fence - base])) ? + 0 : (p+1); +} + +inline <T>* <T>IChunk::pred(<T>* p) const +{ + return ((p-1) < &(data[low - base]) || (p-1) >= &(data[fence - base])) ? + 0 : (p-1); +} + + +// generic Plex operations + +inline <T>Plex::<T>Plex() {} + +inline int <T>Plex::chunk_size() const +{ + return csize; +} + +inline int <T>Plex::ecnef () const +{ + return lo - 1; +} + + +inline int <T>Plex::fence () const +{ + return fnc; +} + +inline int <T>Plex::length () const +{ + return fnc - lo; +} + +inline int <T>Plex::empty () const +{ + return fnc == lo; +} + +inline <T>IChunk* <T>Plex::tl() const +{ + return hd->prev(); +} + +inline int <T>Plex::one_chunk() const +{ + return hd == hd->prev(); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Queue.ccP b/gnu/lib/libg++/g++-include/gen/Queue.ccP new file mode 100644 index 00000000000..fb48d952ff7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Queue.ccP @@ -0,0 +1,14 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.Queue.h" + +<T>Queue::~<T>Queue() {} + + +// error handling + +void <T>Queue::error(const char* msg) +{ + (*lib_error_handler)("Queue", msg); +} diff --git a/gnu/lib/libg++/g++-include/gen/Queue.hP b/gnu/lib/libg++/g++-include/gen/Queue.hP new file mode 100644 index 00000000000..3ff62c865cc --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Queue.hP @@ -0,0 +1,62 @@ +// 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 _<T>Queue_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Queue_h + +#include <builtin.h> + +#include "<T>.defs.h" + +class <T>Queue +{ +public: + <T>Queue(); + virtual ~<T>Queue(); + + virtual void enq(<T&> item) = 0; + virtual <T> deq() = 0; + virtual <T>& 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; +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>Queue::<T>Queue() {} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/RAVLMap.ccP b/gnu/lib/libg++/g++-include/gen/RAVLMap.ccP new file mode 100644 index 00000000000..815342330a5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/RAVLMap.ccP @@ -0,0 +1,684 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.<C>.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(<T><C>RAVLNode* t) +{ + return t->stat & AVLBALANCEMASK; +} + +static inline void set_bf(<T><C>RAVLNode* t, int b) +{ + t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK); +} + + +static inline int rthread(<T><C>RAVLNode* t) +{ + return t->stat & RTHREADBIT; +} + +static inline void set_rthread(<T><C>RAVLNode* t, int b) +{ + if (b) + t->stat |= RTHREADBIT; + else + t->stat &= ~RTHREADBIT; +} + +static inline int lthread(<T><C>RAVLNode* t) +{ + return t->stat & LTHREADBIT; +} + +static inline void set_lthread(<T><C>RAVLNode* t, int b) +{ + if (b) + t->stat |= LTHREADBIT; + else + t->stat &= ~LTHREADBIT; +} + +/* + traversal primitives +*/ + + +<T><C>RAVLNode* <T><C>RAVLMap::leftmost() +{ + <T><C>RAVLNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T><C>RAVLNode* <T><C>RAVLMap::rightmost() +{ + <T><C>RAVLNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T><C>RAVLNode* <T><C>RAVLMap::succ(<T><C>RAVLNode* t) +{ + <T><C>RAVLNode* r = t->rt; + if (!rthread(t)) while (!lthread(r)) r = r->lt; + return r; +} + +<T><C>RAVLNode* <T><C>RAVLMap::pred(<T><C>RAVLNode* t) +{ + <T><C>RAVLNode* l = t->lt; + if (!lthread(t)) while (!rthread(l)) l = l->rt; + return l; +} + + +Pix <T><C>RAVLMap::seek(<T&> key) +{ + <T><C>RAVLNode* t = root; + if (t == 0) + return 0; + for (;;) + { + int cmp = <T>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 <T><C>RAVLMap::rankof(<T&> key) +{ + int r; + <T><C>RAVLNode* t = root; + if (t == 0) + return 0; + for (r=t->rank; t != 0; r+=t->rank) + { + int cmp = <T>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 <T><C>RAVLMap::ranktoPix(int i) +{ + int r; + <T><C>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 <T>* _target_item; // add/del_item target +static <T><C>RAVLNode* _found_node; // returned added/deleted node +static int _already_found; // for deletion subcases +static int _rank_changed; // for rank computation + + +void <T><C>RAVLMap:: _add(<T><C>RAVLNode*& t) +{ + int cmp = <T>CMP(*_target_item, t->item); + if (cmp == 0) + { + _found_node = t; + return; + } + else if (cmp < 0) + { + if (lthread(t)) + { + ++count; + _found_node = new <T><C>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: + <T><C>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 + { + <T><C>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 <T><C>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: + <T><C>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 + { + <T><C>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; + } + } + } + } +} + + +<C>& <T><C>RAVLMap::operator [] (<T&> item) +{ + if (root == 0) + { + ++count; + root = new <T><C>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 <T><C>RAVLMap::_del(<T><C>RAVLNode* par, <T><C>RAVLNode*& t) +{ + int comp; + if (_already_found) + { + if (rthread(t)) + comp = 0; + else + comp = 1; + } + else + comp = <T>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; + <T><C>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; + <T><C>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 + { + <T><C>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: + <T><C>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: + <T><C>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: + <T><C>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: + <T><C>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 <T><C>RAVLMap::del(<T&> 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 <T><C>RAVLMap::_kill(<T><C>RAVLNode* t) +{ + if (t != 0) + { + if (!lthread(t)) _kill(t->lt); + if (!rthread(t)) _kill(t->rt); + delete t; + } +} + + +<T><C>RAVLMap::<T><C>RAVLMap(<T><C>RAVLMap& b) :<T><C>Map(b.def) +{ + root = 0; + count = 0; + for (Pix i = b.first(); i != 0; b.next(i)) + (*this)[b.key(i)] = b.contents(i); +} + + +int <T><C>RAVLMap::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T><C>RAVLNode* trail = leftmost(); + v &= rankof(trail->item) == n; + <T><C>RAVLNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/RAVLMap.hP b/gnu/lib/libg++/g++-include/gen/RAVLMap.hP new file mode 100644 index 00000000000..cf216e5ba02 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/RAVLMap.hP @@ -0,0 +1,162 @@ +// 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 _<T><C>RAVLMap_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>RAVLMap_h 1 + +#include "<T>.<C>.Map.h" + +struct <T><C>RAVLNode +{ + <T><C>RAVLNode* lt; + <T><C>RAVLNode* rt; + <T> item; + <C> cont; + int rank; + char stat; + <T><C>RAVLNode(<T&> h, <C&> c, + <T><C>RAVLNode* l=0, <T><C>RAVLNode* r=0, int k=1); + ~<T><C>RAVLNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>RAVLNode::<T><C>RAVLNode(<T&> h, <C&> c, + <T><C>RAVLNode* l, <T><C>RAVLNode* r, int k) + :item(h), cont(c), lt(l), rt(r), rank(k), stat(0) {} + +inline <T><C>RAVLNode::~<T><C>RAVLNode() {} + +#endif + +typedef <T><C>RAVLNode* <T><C>RAVLNodePtr; + + +class <T><C>RAVLMap : public <T><C>Map +{ +protected: + <T><C>RAVLNode* root; + + <T><C>RAVLNode* leftmost(); + <T><C>RAVLNode* rightmost(); + <T><C>RAVLNode* pred(<T><C>RAVLNode* t); + <T><C>RAVLNode* succ(<T><C>RAVLNode* t); + void _kill(<T><C>RAVLNode* t); + void _add(<T><C>RAVLNode*& t); + void _del(<T><C>RAVLNode* p, <T><C>RAVLNode*& t); + +public: + <T><C>RAVLMap(<C&> dflt); + <T><C>RAVLMap(<T><C>RAVLMap& a); + ~<T><C>RAVLMap(); + + <C>& operator [] (<T&> key); + + void del(<T&> key); + + Pix first(); + void next(Pix& i); + <T>& key(Pix i); + <C>& contents(Pix i); + + Pix seek(<T&> key); + int contains(<T&> key); + + Pix ranktoPix(int i); + int rankof(<T&> key); + + void clear(); + + Pix last(); + void prev(Pix& i); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>RAVLMap::~<T><C>RAVLMap() +{ + _kill(root); +} + +inline <T><C>RAVLMap::<T><C>RAVLMap(<C&> dflt) :(dflt) +{ + root = 0; +} + + +inline Pix <T><C>RAVLMap::first() +{ + return Pix(leftmost()); +} + +inline Pix <T><C>RAVLMap::last() +{ + return Pix(rightmost()); +} + +inline void <T><C>RAVLMap::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T><C>RAVLNode*)i)); +} + +inline void <T><C>RAVLMap::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T><C>RAVLNode*)i)); +} + +inline <T>& <T><C>RAVLMap::key(Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>RAVLNode*)i)->item; +} + +inline <C>& <T><C>RAVLMap::contents(Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>RAVLNode*)i)->cont; +} + +inline void <T><C>RAVLMap::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T><C>RAVLMap::contains(<T&> key) +{ + return seek(key) != 0; +} + + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/RPlex.ccP b/gnu/lib/libg++/g++-include/gen/RPlex.ccP new file mode 100644 index 00000000000..a91bbeb80ec --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/RPlex.ccP @@ -0,0 +1,492 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.RPlex.h" + +typedef <T>IChunk* _<T>IChunk_ptr; + +<T>RPlex:: <T>RPlex() +{ + lo = fnc = 0; + csize = DEFAULT_INITIAL_CAPACITY; + <T>* data = new <T>[csize]; + set_cache(new <T>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 _<T>IChunk_ptr[maxch]; + chunks[lch] = ch; +} + +<T>RPlex:: <T>RPlex(int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + lo = fnc = 0; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, lo, lo, fnc, csize+lo)); + hd = ch; + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>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 _<T>IChunk_ptr[maxch]; + chunks[lch] = ch; +} + + +<T>RPlex:: <T>RPlex(int l, int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + lo = fnc = l; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, lo, lo, fnc, lo+csize)); + hd = ch; + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>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 _<T>IChunk_ptr[maxch]; + chunks[lch] = ch; +} + +void <T>RPlex::make_initial_chunks(int up) +{ + 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; + <T>* data = new <T> [csize]; + <T>IChunk* h = new <T>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; + <T>* data = new <T> [csize]; + <T>IChunk* h = new <T>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((<T>IChunk*)hd); + + maxch = MIN_NCHUNKS; + if (maxch < count * 2) + maxch = count * 2; + chunks = new _<T>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); +} + +<T>RPlex:: <T>RPlex(int l, int hi, const <T&> initval, int chunksize) +{ + 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); +} + +<T>RPlex::<T>RPlex(const <T>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 <T>RPlex::operator= (const <T>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 <T>RPlex::cache(const <T>* p) const +{ + const <T>IChunk* old = ch; + const <T>IChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = (t->next()); + if (t == old) index_error(); + } + set_cache(t); +} + +int <T>RPlex::owns(Pix px) const +{ + <T>* p = (<T>*)px; + const <T>IChunk* old = ch; + const <T>IChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = (t->next()); + if (t == old) return 0; + } + set_cache(t); + return 1; +} + + +<T>* <T>RPlex::dosucc(const <T>* p) const +{ + if (p == 0) return 0; + const <T>IChunk* old = ch; + const <T>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); +} + +<T>* <T>RPlex::dopred(const <T>* p) const +{ + if (p == 0) return 0; + const <T>IChunk* old = ch; + const <T>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 <T>RPlex::add_high(const <T&> elem) +{ + <T>IChunk* t = tl(); + if (!t->can_grow_high()) + { + if (t-><T>IChunk::empty() && one_chunk()) + { + t->clear(fnc); + base = t->base_index() - lch * csize; + } + else + { + <T>* data = new <T> [csize]; + t = (new <T>IChunk(data, fnc, fnc, fnc,fnc+csize)); + t->link_to_prev(tl()); + if (fch == maxch) + { + maxch *= 2; + <T>IChunk** newch = new _<T>IChunk_ptr [maxch]; + bcopy(chunks, newch, fch * sizeof(_<T>IChunk_ptr)); + delete chunks; + chunks = newch; + } + chunks[fch++] = t; + } + } + *((t-><T>IChunk::grow_high())) = elem; + set_cache(t); + return fnc++; +} + +int <T>RPlex::del_high () +{ + if (empty()) empty_error(); + <T>IChunk* t = tl(); + if (t-><T>IChunk::empty()) // kill straggler first + { + <T>IChunk* pred = t->prev(); + del_chunk(t); + t = (pred); + --fch; + } + t-><T>IChunk::shrink_high(); + if (t-><T>IChunk::empty() && !one_chunk()) + { + <T>IChunk* pred = t->prev(); + del_chunk(t); + t = (pred); + --fch; + } + set_cache(t); + return --fnc - 1; +} + +int <T>RPlex::add_low (const <T&> elem) +{ + <T>IChunk* t = hd; + if (!t->can_grow_low()) + { + if (t-><T>IChunk::empty() && one_chunk()) + { + t->cleardown(lo); + base = t->base_index() - lch * csize; + } + else + { + <T>* data = new <T> [csize]; + hd = new <T>IChunk(data, lo-csize, lo, lo, lo); + hd->link_to_next(t); + t = ( hd); + if (lch == 0) + { + lch = maxch; + fch += maxch; + maxch *= 2; + <T>IChunk** newch = new _<T>IChunk_ptr [maxch]; + bcopy(chunks, &(newch[lch]), lch * sizeof(_<T>IChunk_ptr)); + delete chunks; + chunks = newch; + base = t->base_index() - (lch - 1) * csize; + } + chunks[--lch] = t; + } + } + *((t-><T>IChunk::grow_low())) = elem; + set_cache(t); + return --lo; +} + + +int <T>RPlex::del_low () +{ + if (empty()) empty_error(); + <T>IChunk* t = hd; + if (t-><T>IChunk::empty()) + { + hd = t->next(); + del_chunk(t); + t = hd; + ++lch; + } + t-><T>IChunk::shrink_low(); + if (t-><T>IChunk::empty() && !one_chunk()) + { + hd = t->next(); + del_chunk(t); + t = hd; + ++lch; + } + set_cache(t); + return ++lo; +} + +void <T>RPlex::append(const <T>RPlex& a) +{ + for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); +} + +void <T>RPlex::prepend (const <T>RPlex& a) +{ + for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); +} + +void <T>RPlex::reverse() +{ + <T> tmp; + int l = lo; + int h = fnc - 1; + <T>IChunk* loch = hd; + <T>IChunk* hich = tl(); + while (l < h) + { + <T>* lptr = loch->pointer_to(l); + <T>* 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 <T>RPlex::fill(const <T&> x) +{ + for (int i = lo; i < fnc; ++i) (*this)[i] = x; +} + +void <T>RPlex::fill(const <T&> x, int lo, int hi) +{ + for (int i = lo; i <= hi; ++i) (*this)[i] = x; +} + + +void <T>RPlex::clear() +{ + for (int i = lch + 1; i < fch; ++i) + del_chunk(chunks[i]); + fch = lch + 1; + set_cache(chunks[lch]); + ch-><T>IChunk::clear(lo); + fnc = lo; +} + +int <T>RPlex::reset_low(int l) +{ + int old = lo; + int diff = l - lo; + if (diff != 0) + { + lo += diff; + fnc += diff; + <T>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 <T>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-><T>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 <T>IChunk* t = (hd); + for (;;) + { + v &= chunks[k++] == t; // each chunk is at proper index + if (t == ch) ++found_ch; + v &= t-><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; +} diff --git a/gnu/lib/libg++/g++-include/gen/RPlex.hP b/gnu/lib/libg++/g++-include/gen/RPlex.hP new file mode 100644 index 00000000000..7a21f5bb649 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/RPlex.hP @@ -0,0 +1,268 @@ +// 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 _<T>RPlex_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>RPlex_h 1 + +#include "<T>.Plex.h" + +// minimum number of chunks to index + +#ifndef MIN_NCHUNKS +#define MIN_NCHUNKS 16 +#endif + +class <T>RPlex: public <T>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 + <T>IChunk** chunks; // array of chunks + <T>IChunk* ch; // cached chunk + + void make_initial_chunks(int up = 1); + + void cache(int idx) const; + void cache(const <T>* p) const; + <T>* dopred(const <T>* p) const; + <T>* dosucc(const <T>* p) const; + + void set_cache(const <T>IChunk* t) const; // logically, + // not physically const + +public: + <T>RPlex(); // set low = 0; + // fence = 0; + // csize = default + + <T>RPlex(int ch_size); // low = 0; + // fence = 0; + // csize = ch_size + + <T>RPlex(int lo, // low = lo; + int ch_size); // fence=lo + // csize = ch_size + + <T>RPlex(int lo, // low = lo + int hi, // fence = hi+1 + const <T&> initval,// fill with initval, + int ch_size = 0); // csize= ch_size + // or fence-lo if 0 + + <T>RPlex(const <T>RPlex&); + + ~<T>RPlex(); + + void operator= (const <T>RPlex&); + +// virtuals + + <T>& high_element (); + <T>& low_element (); + + const <T>& high_element () const; + const <T>& low_element () const; + + Pix first() const; + Pix last() const; + void prev(Pix& ptr) const; + void next(Pix& ptr) const; + int owns(Pix p) const; + <T>& operator () (Pix p); + const <T>& 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; + <T>& operator [] (int index); + const <T>& 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 <T&> elem); + int del_high (); + int add_low (const <T&> elem); + int del_low (); + + void fill(const <T&> x); + void fill(const <T&> x, int from, int to); + void clear(); + void reverse(); + void append(const <T>RPlex& a); + void prepend(const <T>RPlex& a); + + int reset_low(int newlow); + + int OK () const; +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline void <T>RPlex::prev(int& idx) const +{ + --idx; +} + +inline void <T>RPlex::next(int& idx) const +{ + ++idx; +} + +inline int <T>RPlex::full () const +{ + return 0; +} + +inline int <T>RPlex::can_add_high() const +{ + return 1; +} + +inline int <T>RPlex::can_add_low() const +{ + return 1; +} + +inline int <T>RPlex::valid (int idx) const +{ + return idx >= lo && idx < fnc; +} + +inline int <T>RPlex::low() const +{ + return lo; +} + +inline int <T>RPlex::high() const +{ + return fnc - 1; +} + +inline void <T>RPlex::set_cache(const <T>IChunk* t) const +{ + ((<T>RPlex*)(this))->ch = (<T>IChunk*)t; +} + +inline void <T>RPlex::cache(int idx) const +{ + if (idx < lo || idx >= fnc) index_error(); + set_cache(chunks[(idx - base) / csize]); +} + +inline <T>& <T>RPlex::low_element () +{ + cache(lo); return *(ch->pointer_to(lo)); +} + +inline <T>& <T>RPlex::high_element () +{ + cache(fnc-1); return *(ch->pointer_to(fnc - 1)); +} + +inline const <T>& <T>RPlex::low_element () const +{ + cache(lo); return *((const <T>*)(ch->pointer_to(lo))); +} + +inline const <T>& <T>RPlex::high_element () const +{ + cache(fnc-1); return *((const <T>*)(ch->pointer_to(fnc - 1))); +} + +inline int <T>RPlex::Pix_to_index(Pix px) const +{ + <T>* p = (<T>*)px; + if (!ch->actual_pointer(p)) cache(p); + return ch->index_of(p); +} + +inline Pix <T>RPlex::index_to_Pix(int idx) const +{ + if (!ch->actual_index(idx)) cache(idx); + return (Pix)(ch->pointer_to(idx)); +} + +inline Pix <T>RPlex::first() const +{ + return Pix(hd-><T>IChunk::first_pointer()); +} + +inline Pix <T>RPlex::last() const +{ + return Pix(tl()-><T>IChunk::last_pointer()); +} + +inline void <T>RPlex::prev(Pix& p) const +{ + Pix q = Pix(ch-><T>IChunk::pred((<T>*)p)); + p = (q == 0)? Pix(dopred((<T>*)p)) : q; +} + +inline void <T>RPlex::next(Pix& p) const +{ + Pix q = Pix(ch-><T>IChunk::succ((<T>*)p)); + p = (q == 0)? Pix(dosucc((<T>*)p)) : q; +} + +inline <T>& <T>RPlex:: operator () (Pix p) +{ + return *((<T>*)p); +} + + +inline <T>& <T>RPlex:: operator [] (int idx) +{ + cache(idx); return *(ch->pointer_to(idx)); +} + +inline const <T>& <T>RPlex:: operator () (Pix p) const +{ + return *((const <T>*)p); +} + +inline const <T>& <T>RPlex:: operator [] (int idx) const +{ + cache(idx); return *((const <T>*)(ch->pointer_to(idx))); +} + +inline <T>RPlex::~<T>RPlex() +{ + delete chunks; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SLBag.ccP b/gnu/lib/libg++/g++-include/gen/SLBag.ccP new file mode 100644 index 00000000000..172a652da31 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLBag.ccP @@ -0,0 +1,110 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.SLBag.h" + +int <T>SLBag::OK() +{ + int v = p.OK(); + v &= count == p.length(); + if (!v) error("invariant failure"); + return v; +} + +Pix <T>SLBag::seek(<T&> item, Pix i) +{ + if (i == 0) i = first(); else next(i); + for (; i != 0 && (!(<T>EQ(p(i), item))); p.next(i)); + return i; +} + +int <T>SLBag::nof(<T&> item) +{ + int n = 0; + for (Pix p = first(); p; next(p)) if (<T>EQ((*this)(p), item)) ++n; + return n; +} + + +void <T>SLBag::del(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + return; + else if (<T>EQ(p(i), item)) + { + --count; + p.del_front(); + } + else + { + Pix trail = i; + p.next(i); + while (i != 0) + { + if (<T>EQ(p(i), item)) + { + --count; + p.del_after(trail); + return; + } + trail = i; + p.next(i); + } + } +} + +void <T>SLBag::remove(<T&> item) +{ + Pix i = p.first(); + while (i != 0 && <T>EQ(p(i), item)) + { + --count; + p.del_front(); + i = p.first(); + } + if (i != 0) + { + Pix trail = i; + p.next(i); + while (i != 0) + { + if (<T>EQ(p(i), item)) + { + --count; + p.del_after(trail); + i = trail; + p.next(i); + } + else + { + trail = i; + p.next(i); + } + } + } +} + diff --git a/gnu/lib/libg++/g++-include/gen/SLBag.hP b/gnu/lib/libg++/g++-include/gen/SLBag.hP new file mode 100644 index 00000000000..d039241668d --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLBag.hP @@ -0,0 +1,104 @@ +// 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 _<T>SLBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SLBag_h 1 + +#include "<T>.Bag.h" +#include "<T>.SLList.h" + +class <T>SLBag : public <T>Bag +{ +protected: + <T>SLList p; + +public: + <T>SLBag(); + <T>SLBag(const <T>SLBag&); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int contains(<T&> item); + int nof(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item, Pix from = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLBag::<T>SLBag() : p() { count = 0; } + +inline <T>SLBag::<T>SLBag(const <T>SLBag& s) : p(s.p) { count = s.count; } + +inline Pix <T>SLBag::first() +{ + return p.first(); +} + +inline void <T>SLBag::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>SLBag::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>SLBag::clear() +{ + count = 0; p.clear(); +} + +inline int <T>SLBag::owns (Pix idx) +{ + return p.owns(idx); +} + +inline Pix <T>SLBag::add(<T&> item) +{ + ++count; + return p.append(item); +} + +inline int <T>SLBag::contains(<T&> item) +{ + return seek(item) != 0; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SLList.ccP b/gnu/lib/libg++/g++-include/gen/SLList.ccP new file mode 100644 index 00000000000..57920c3190f --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLList.ccP @@ -0,0 +1,296 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <values.h> +#include <stream.h> +#include "<T>.SLList.h" + + +void <T>SLList::error(const char* msg) +{ + (*lib_error_handler)("SLList", msg); +} + +int <T>SLList::length() +{ + int l = 0; + <T>SLListNode* t = last; + if (t != 0) do { ++l; t = t->tl; } while (t != last); + return l; +} + +<T>SLList::<T>SLList(<T>SLList& a) +{ + if (a.last == 0) + last = 0; + else + { + <T>SLListNode* p = a.last->tl; + <T>SLListNode* h = new <T>SLListNode(p->hd); + last = h; + for (;;) + { + if (p == a.last) + { + last->tl = h; + return; + } + p = p->tl; + <T>SLListNode* n = new <T>SLListNode(p->hd); + last->tl = n; + last = n; + } + } +} + +<T>SLList& <T>SLList::operator = (<T>SLList& a) +{ + if (last != a.last) + { + clear(); + if (a.last != 0) + { + <T>SLListNode* p = a.last->tl; + <T>SLListNode* h = new <T>SLListNode(p->hd); + last = h; + for (;;) + { + if (p == a.last) + { + last->tl = h; + break; + } + p = p->tl; + <T>SLListNode* n = new <T>SLListNode(p->hd); + last->tl = n; + last = n; + } + } + } + return *this; +} + +void <T>SLList::clear() +{ + if (last == 0) + return; + + <T>SLListNode* p = last->tl; + last->tl = 0; + last = 0; + + while (p != 0) + { + <T>SLListNode* nxt = p->tl; + delete(p); + p = nxt; + } +} + + +Pix <T>SLList::prepend(<T&> item) +{ + <T>SLListNode* t = new <T>SLListNode(item); + if (last == 0) + t->tl = last = t; + else + { + t->tl = last->tl; + last->tl = t; + } + return Pix(t); +} + + +Pix <T>SLList::prepend(<T>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 <T>SLList::append(<T&> item) +{ + <T>SLListNode* t = new <T>SLListNode(item); + if (last == 0) + t->tl = last = t; + else + { + t->tl = last->tl; + last->tl = t; + last = t; + } + return Pix(t); +} + +Pix <T>SLList::append(<T>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 <T>SLList::join(<T>SLList& b) +{ + <T>SLListNode* t = b.last; + b.last = 0; + if (last == 0) + last = t; + else if (t != 0) + { + <T>SLListNode* f = last->tl; + last->tl = t->tl; + t->tl = f; + last = t; + } +} + +Pix <T>SLList::ins_after(Pix p, <T&> item) +{ + <T>SLListNode* u = (<T>SLListNode*)p; + <T>SLListNode* t = new <T>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 <T>SLList::del_after(Pix p) +{ + <T>SLListNode* u = (<T>SLListNode*)p; + if (last == 0 || u == last) error("cannot del_after last"); + if (u == 0) u = last; // del_after 0 means delete first + <T>SLListNode* t = u->tl; + if (u == t) + last = 0; + else + { + u->tl = t->tl; + if (last == t) + last = u; + } + delete t; +} + +int <T>SLList::owns(Pix p) +{ + <T>SLListNode* t = last; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->tl; + } while (t != last); + } + return 0; +} + +<T> <T>SLList::remove_front() +{ + if (last == 0) error("remove_front of empty list"); + <T>SLListNode* t = last->tl; + <T> res = t->hd; + if (t == last) + last = 0; + else + last->tl = t->tl; + delete t; + return res; +} + +int <T>SLList::remove_front(<T>& x) +{ + if (last == 0) + return 0; + else + { + <T>SLListNode* t = last->tl; + x = t->hd; + if (t == last) + last = 0; + else + last->tl = t->tl; + delete t; + return 1; + } +} + + +void <T>SLList::del_front() +{ + if (last == 0) error("del_front of empty list"); + <T>SLListNode* t = last->tl; + if (t == last) + last = 0; + else + last->tl = t->tl; + delete t; +} + +int <T>SLList::OK() +{ + int v = 1; + if (last != 0) + { + <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/SLList.hP b/gnu/lib/libg++/g++-include/gen/SLList.hP new file mode 100644 index 00000000000..1886b68f1a1 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLList.hP @@ -0,0 +1,152 @@ +// 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 _<T>SLList_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SLList_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +#ifndef _<T>SLListNode_h +#define _<T>SLListNode_h 1 + +struct <T>SLListNode +{ + <T>SLListNode* tl; + <T> hd; + <T>SLListNode(); + <T>SLListNode(<T&> h, <T>SLListNode* t = 0); + ~<T>SLListNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLListNode::<T>SLListNode() {} + +inline <T>SLListNode::<T>SLListNode(<T&> h, <T>SLListNode* t) :hd(h), tl(t) {} + +inline <T>SLListNode::~<T>SLListNode() {} + +#endif + +typedef <T>SLListNode* <T>SLListNodePtr; + +#endif + + +class <T>SLList +{ +protected: + <T>SLListNode* last; + +public: + <T>SLList(); + <T>SLList(<T>SLList& a); + ~<T>SLList(); + + <T>SLList& operator = (<T>SLList& a); + + int empty(); + int length(); + + void clear(); + + Pix prepend(<T&> item); + Pix append(<T&> item); + + void join(<T>SLList&); + + Pix prepend(<T>SLListNode*); + Pix append(<T>SLListNode*); + + <T>& operator () (Pix p); + Pix first(); + void next(Pix& p); + int owns(Pix p); + Pix ins_after(Pix p, <T&> item); + void del_after(Pix p); + + <T>& front(); + <T>& rear(); + <T> remove_front(); + int remove_front(<T>& x); + void del_front(); + + void error(const char* msg); + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLList::~<T>SLList() +{ + clear(); +} + +inline <T>SLList::<T>SLList() +{ + last = 0; +} + +inline int <T>SLList::empty() +{ + return last == 0; +} + + +inline Pix <T>SLList::first() +{ + return (last == 0)? 0 : Pix(last->tl); +} + +inline void <T>SLList::next(Pix& p) +{ + p = (p == 0 || p == last)? 0 : Pix(((<T>SLListNode*)(p))->tl); +} + +inline <T>& <T>SLList::operator () (Pix p) +{ + if (p == 0) error("null Pix"); + return ((<T>SLListNode*)(p))->hd; +} + +inline <T>& <T>SLList::front() +{ + if (last == 0) error("front: empty list"); + return last->tl->hd; +} + +inline <T>& <T>SLList::rear() +{ + if (last == 0) error("rear: empty list"); + return last->hd; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SLQueue.ccP b/gnu/lib/libg++/g++-include/gen/SLQueue.ccP new file mode 100644 index 00000000000..8a5935b7757 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLQueue.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.SLQueue.h" diff --git a/gnu/lib/libg++/g++-include/gen/SLQueue.hP b/gnu/lib/libg++/g++-include/gen/SLQueue.hP new file mode 100644 index 00000000000..5e75031d3da --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLQueue.hP @@ -0,0 +1,118 @@ +// 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 _<T>SLQueue_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SLQueue_h + +#include "<T>.SLList.h" +#include "<T>.Queue.h" + +class <T>SLQueue : public <T>Queue +{ + <T>SLList p; + +public: + <T>SLQueue(); + <T>SLQueue(const <T>SLQueue& q); + ~<T>SLQueue(); + + void operator = (const <T>SLQueue&); + + void enq(<T&> item); + <T> deq(); + <T>& front(); + void del_front(); + + void clear(); + int empty(); + int full(); + int length(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLQueue::<T>SLQueue() :p() {} +inline <T>SLQueue::<T>SLQueue(const <T>SLQueue& q) : p(q.p) {} + +inline <T>SLQueue::~<T>SLQueue() {} + +inline void <T>SLQueue::enq(<T&>item) +{ + p.append(item); +} + +inline <T> <T>SLQueue::deq() +{ + return p.remove_front(); +} + +inline <T>& <T>SLQueue::front() +{ + return p.front(); +} + + +inline void <T>SLQueue::del_front() +{ + p.del_front(); +} + +inline void <T>SLQueue::operator =(const <T>SLQueue& s) +{ + p = s.p; +} + +inline int <T>SLQueue::empty() +{ + return p.empty(); +} + +inline int <T>SLQueue::full() +{ + return 0; +} + +inline int <T>SLQueue::length() +{ + return p.length(); +} + +inline int <T>SLQueue::OK() +{ + return p.OK(); +} + +inline void <T>SLQueue::clear() +{ + p.clear(); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SLSet.ccP b/gnu/lib/libg++/g++-include/gen/SLSet.ccP new file mode 100644 index 00000000000..5854b2bbbfa --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLSet.ccP @@ -0,0 +1,81 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.SLSet.h" + +int <T>SLSet::OK() +{ + int v = p.OK(); + v &= count == p.length(); + if (!v) error("invariant failure"); + return v; +} + +Pix <T>SLSet::seek(<T&> item) +{ + for (Pix i = p.first(); i != 0 && !<T>EQ(p(i),item); p.next(i)); + return i; +} + +Pix <T>SLSet::add(<T&> item) +{ + Pix i = seek(item); + if (i == 0) + { + ++count; + i = p.append(item); + } + return i; +} + +void <T>SLSet::del(<T&> item) +{ + Pix i = p.first(); + if (i == 0) + return; + else if (<T>EQ(p(i), item)) + { + --count; + p.del_front(); + } + else + { + Pix trail = i; + p.next(i); + while (i != 0) + { + if (<T>EQ(p(i), item)) + { + --count; + p.del_after(trail); + return; + } + trail = i; + p.next(i); + } + } +} + diff --git a/gnu/lib/libg++/g++-include/gen/SLSet.hP b/gnu/lib/libg++/g++-include/gen/SLSet.hP new file mode 100644 index 00000000000..bc11a74c042 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLSet.hP @@ -0,0 +1,97 @@ +// 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 _<T>SLSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SLSet_h 1 + +#include "<T>.Set.h" +#include "<T>.SLList.h" + +class <T>SLSet : public <T>Set +{ +protected: + <T>SLList p; + +public: + <T>SLSet(); + <T>SLSet(const <T>SLSet&); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLSet::<T>SLSet() : p() { count = 0; } + +inline <T>SLSet::<T>SLSet(const <T>SLSet& s) : p(s.p) { count = s.count; } + +inline Pix <T>SLSet::first() +{ + return p.first(); +} + +inline void <T>SLSet::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>SLSet::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>SLSet::clear() +{ + count = 0; p.clear(); +} + +inline int <T>SLSet::contains (<T&> item) +{ + return seek(item) != 0; +} + +inline int <T>SLSet::owns (Pix idx) +{ + return p.owns(idx); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SLStack.ccP b/gnu/lib/libg++/g++-include/gen/SLStack.ccP new file mode 100644 index 00000000000..3996b41fac5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLStack.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.SLStack.h" diff --git a/gnu/lib/libg++/g++-include/gen/SLStack.hP b/gnu/lib/libg++/g++-include/gen/SLStack.hP new file mode 100644 index 00000000000..dced4672063 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SLStack.hP @@ -0,0 +1,119 @@ +// 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 _<T>SLStack_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SLStack_h 1 + +#include "<T>.SLList.h" +#include "<T>.Stack.h" + +class <T>SLStack : public <T>Stack +{ + <T>SLList p; + +public: + <T>SLStack(); + <T>SLStack(const <T>SLStack& s); + ~<T>SLStack(); + + void operator = (const <T>SLStack&); + + void push(<T&> item); + <T> pop(); + <T>& top(); + void del_top(); + + int empty(); + int full(); + int length(); + + void clear(); + + int OK(); + +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SLStack::<T>SLStack() :p() {} +inline <T>SLStack::<T>SLStack(const <T>SLStack& a) : p(a.p) {} +inline <T>SLStack::~<T>SLStack() {} + +inline void <T>SLStack::push(<T&> item) +{ + p.prepend(item); +} + +inline <T> <T>SLStack::pop() +{ + return p.remove_front(); +} + +inline <T>& <T>SLStack::top() +{ + return p.front(); +} + +inline void <T>SLStack::del_top() +{ + p.del_front(); +} + +inline void <T>SLStack::operator =(const <T>SLStack& s) +{ + p = s.p; +} + +inline int <T>SLStack::empty() +{ + return p.empty(); +} + +inline int <T>SLStack::full() +{ + return 0; +} + +inline int <T>SLStack::length() +{ + return p.length(); +} + +inline int <T>SLStack::OK() +{ + return p.OK(); +} + +inline void <T>SLStack::clear() +{ + p.clear(); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Set.ccP b/gnu/lib/libg++/g++-include/gen/Set.ccP new file mode 100644 index 00000000000..c47260227a7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Set.ccP @@ -0,0 +1,121 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include "<T>.Set.h" + + +Pix <T>Set::seek(<T&> item) +{ + for (Pix i = first(); i != 0 && !(<T>EQ((*this)(i), item)); next(i)); + return i; +} + +int <T>Set::owns(Pix idx) +{ + if (idx == 0) return 0; + for (Pix i = first(); i; next(i)) if (i == idx) return 1; + return 0; +} + +void <T>Set::clear() +{ + Pix i = first(); + while (i != 0) + { + del((*this)(i)); + i = first(); + } +} + +int <T>Set::contains (<T&> item) +{ + return seek(item) != 0; +} + +int <T>Set::operator <= (<T>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 <T>Set::operator == (<T>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 <T>Set::operator != (<T>Set& b) +{ + return !(*this == b); +} + +void <T>Set::operator |= (<T>Set& b) +{ + if (&b != this) + for (Pix i = b.first(); i; b.next(i)) add(b(i)); +} + +void <T>Set::operator -= (<T>Set& b) +{ + if (&b == this) + clear(); + else + for (Pix i = b.first(); i; b.next(i)) del(b(i)); +} + + +void <T>Set::operator &= (<T>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 <T>Set::error(const char* msg) +{ + (*lib_error_handler)("Set", msg); +} diff --git a/gnu/lib/libg++/g++-include/gen/Set.hP b/gnu/lib/libg++/g++-include/gen/Set.hP new file mode 100644 index 00000000000..b2c08cea002 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Set.hP @@ -0,0 +1,88 @@ +// 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 _<T>Set_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Set_h 1 + +#include <Pix.h> +#include "<T>.defs.h" + +class <T>Set +{ +protected: + + int count; + +public: + virtual ~<T>Set(); + + int length(); // current number of items + int empty(); + + virtual Pix add(<T&> item) = 0; // add item; return Pix + virtual void del(<T&> item) = 0; // delete item + virtual int contains(<T&> 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 <T>& operator () (Pix i) = 0; // access item at i + + virtual int owns(Pix i); // is i a valid Pix ? + virtual Pix seek(<T&> item); // Pix of item + + void operator |= (<T>Set& b); // add all items in b + void operator -= (<T>Set& b); // delete items also in b + void operator &= (<T>Set& b); // delete items not in b + + int operator == (<T>Set& b); + int operator != (<T>Set& b); + int operator <= (<T>Set& b); + + void error(const char* msg); + virtual int OK() = 0; // rep invariant +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>Set::~<T>Set() {} + +inline int <T>Set::length() +{ + return count; +} + +inline int <T>Set::empty() +{ + return count == 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SplayBag.ccP b/gnu/lib/libg++/g++-include/gen/SplayBag.ccP new file mode 100644 index 00000000000..1e16a7e45d0 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayBag.ccP @@ -0,0 +1,451 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.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 +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; +} _dummy_null; + + +/* + traversal primitives +*/ + + +<T>SplayNode* <T>SplayBag::leftmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T>SplayNode* <T>SplayBag::rightmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T>SplayNode* <T>SplayBag::succ(<T>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; + } + } +} + +<T>SplayNode* <T>SplayBag::pred(<T>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 <T>SplayBag::seek(<T&> key, Pix i) +{ + if (root == 0) return 0; + + <T>SplayNode* t = (<T>SplayNode*) i; + if (t != 0) + { + int cmp = <T>CMP(key, t->item); + if (cmp == 0) + { + t = succ(t); + if (t != 0 && <T>EQ(key, t->item)) + return Pix(t); + else + return 0; + } + else if (cmp < 0) + return 0; + } + + t = root; + int comp = <T>CMP(key, t->item); + if (comp == 0) + return Pix(t); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + break; + else + { + comp = <T>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 = <T>CMP(key, t->item); + } + } + } + else + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + break; + else + { + comp = <T>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 = <T>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 && <T>EQ(l->item, key)) { t = l; l = pred(l); } + return Pix(t); + } +} + +int <T>SplayBag::nof(<T&> item) +{ + int n = 0; + <T>SplayNode* t = (<T>SplayNode*)(seek(item)); + if (t != 0) + { + do + { + ++n; + t = succ(t); + } while (t != 0 && <T>EQ(item, t->item)); + } + return n; +} + +Pix <T>SplayBag::add(<T&> item) +{ + ++count; + <T>SplayNode* newnode = new <T>SplayNode(item); + <T>SplayNode* t = root; + if (t == 0) + { + root = newnode; + return Pix(root); + } + + int comp = <T>CMP(item, t->item); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + int done = 0; + while (!done) + { + if (comp >= 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + { + tr = newnode; + comp = 0; done = 1; + } + else + comp = <T>CMP(item, tr->item); + + if (comp <= 0) + { + l->rt = t; t->par = l; + l = t; + t = tr; + } + else + { + <T>SplayNode* trr = tr->rt; + if (trr == 0) + { + trr = newnode; + comp = 0; done = 1; + } + else + comp = <T>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 + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + { + tl = newnode; + comp = 0; done = 1; + } + else + comp = <T>CMP(item, tl->item); + + if (comp >= 0) + { + r->lt = t; t->par = r; + r = t; + t = tl; + } + else + { + <T>SplayNode* tll = tl->lt; + if (tll == 0) + { + tll = newnode; + comp = 0; done = 1; + } + else + comp = <T>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 <T>SplayBag::_del(<T>SplayNode* t) +{ + if (t == 0) return; + + <T>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 + { + <T>SplayNode* r = t->rt; + <T>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 <T>SplayBag::remove(<T&> key) +{ + <T>SplayNode* t = (<T>SplayNode*)(seek(key)); + while (t != 0) + { + _del(t); + t = (<T>SplayNode*)(seek(key)); + } +} + + +void <T>SplayBag::_kill(<T>SplayNode* t) +{ + if (t != 0) + { + _kill(t->lt); + _kill(t->rt); + delete t; + } +} + + +<T>SplayNode* <T>SplayBag::_copy(<T>SplayNode* t) +{ + if (t != 0) + { + <T>SplayNode* l = _copy(t->lt); + <T>SplayNode* r = _copy(t->rt); + <T>SplayNode* x = new <T>SplayNode(t->item, l, r); + if (l != 0) l->par = x; + if (r != 0) r->par = x; + return x; + } + else + return 0; +} + +int <T>SplayBag::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T>SplayNode* trail = leftmost(); + <T>SplayNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) <= 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} + diff --git a/gnu/lib/libg++/g++-include/gen/SplayBag.hP b/gnu/lib/libg++/g++-include/gen/SplayBag.hP new file mode 100644 index 00000000000..5d3723ba9cf --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayBag.hP @@ -0,0 +1,160 @@ +// 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 _<T>SplayBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SplayBag_h 1 + +#include "<T>.Bag.h" + +#ifndef _<T>SplayNode +#define _<T>SplayNode 1 + +struct <T>SplayNode +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; + <T> item; + <T>SplayNode(<T&> h, <T>SplayNode* l=0, <T>SplayNode* r=0); + ~<T>SplayNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplayNode::<T>SplayNode(<T&> h, <T>SplayNode* l, <T>SplayNode* r) +:item(h), lt(l), rt(r), par(0) {} + +inline <T>SplayNode::~<T>SplayNode() {} + +#endif + +typedef <T>SplayNode* <T>SplayNodePtr; + +#endif + +class <T>SplayBag : public <T>Bag +{ +protected: + <T>SplayNode* root; + + <T>SplayNode* leftmost(); + <T>SplayNode* rightmost(); + <T>SplayNode* pred(<T>SplayNode* t); + <T>SplayNode* succ(<T>SplayNode* t); + void _kill(<T>SplayNode* t); + <T>SplayNode* _copy(<T>SplayNode* t); + void _del(<T>SplayNode* t); + +public: + <T>SplayBag(); + <T>SplayBag(<T>SplayBag& a); + ~<T>SplayBag(); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int nof(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item, Pix from = 0); + + Pix last(); + void prev(Pix& i); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplayBag::~<T>SplayBag() +{ + _kill(root); +} + +inline <T>SplayBag::<T>SplayBag() +{ + root = 0; + count = 0; +} + +inline <T>SplayBag::<T>SplayBag(<T>SplayBag& b) +{ + count = b.count; + root = _copy(b.root); +} + +inline Pix <T>SplayBag::first() +{ + return Pix(leftmost()); +} + +inline Pix <T>SplayBag::last() +{ + return Pix(rightmost()); +} + +inline void <T>SplayBag::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T>SplayNode*)i)); +} + +inline void <T>SplayBag::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T>SplayNode*)i)); +} + +inline <T>& <T>SplayBag::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>SplayNode*)i)->item; +} + +inline void <T>SplayBag::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T>SplayBag::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline void <T>SplayBag::del(<T&> key) +{ + _del((<T>SplayNode*)(seek(key))); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SplayMap.ccP b/gnu/lib/libg++/g++-include/gen/SplayMap.ccP new file mode 100644 index 00000000000..0d86c2dd4ab --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayMap.ccP @@ -0,0 +1,407 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.<C>.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 +{ + <T><C>SplayNode* lt; + <T><C>SplayNode* rt; + <T><C>SplayNode* par; +} _dummy_null; + + +/* + traversal primitives +*/ + + +<T><C>SplayNode* <T><C>SplayMap::leftmost() +{ + <T><C>SplayNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T><C>SplayNode* <T><C>SplayMap::rightmost() +{ + <T><C>SplayNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T><C>SplayNode* <T><C>SplayMap::succ(<T><C>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; + } + } +} + +<T><C>SplayNode* <T><C>SplayMap::pred(<T><C>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 <T><C>SplayMap::seek(<T&> key) +{ + <T><C>SplayNode* t = root; + if (t == 0) + return 0; + + int comp = <T>CMP(key, t->item); + if (comp == 0) + return Pix(t); + + <T><C>SplayNode* dummy = (<T><C>SplayNode*)(&_dummy_null); + <T><C>SplayNode* l = dummy; + <T><C>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T><C>SplayNode* tr = t->rt; + if (tr == 0) + break; + else + { + comp = <T>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 = <T>CMP(key, t->item); + } + } + } + else + { + <T><C>SplayNode* tl = t->lt; + if (tl == 0) + break; + else + { + comp = <T>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 = <T>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; +} + + +<C>& <T><C>SplayMap::operator [] (<T&> item) +{ + <T><C>SplayNode* t = root; + if (t == 0) + { + ++count; + root = new <T><C>SplayNode(item, def); + return root->cont; + } + int comp = <T>CMP(item, t->item); + if (comp == 0) + return t->cont; + + <T><C>SplayNode* dummy = (<T><C>SplayNode*)(&_dummy_null); + <T><C>SplayNode* l = dummy; + <T><C>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T><C>SplayNode* tr = t->rt; + if (tr == 0) + { + ++count; + tr = new <T><C>SplayNode(item, def); + comp = 0; + } + else + comp = <T>CMP(item, tr->item); + + if (comp <= 0) + { + l->rt = t; t->par = l; + l = t; + t = tr; + } + else + { + <T><C>SplayNode* trr = tr->rt; + if (trr == 0) + { + ++count; + trr = new <T><C>SplayNode(item, def); + comp = 0; + } + else + comp = <T>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 + { + <T><C>SplayNode* tl = t->lt; + if (tl == 0) + { + ++count; + tl = new <T><C>SplayNode(item, def); + comp = 0; + } + else + comp = <T>CMP(item, tl->item); + + if (comp >= 0) + { + r->lt = t; t->par = r; + r = t; + t = tl; + } + else + { + <T><C>SplayNode* tll = tl->lt; + if (tll == 0) + { + ++count; + tll = new <T><C>SplayNode(item, def); + comp = 0; + } + else + comp = <T>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 <T><C>SplayMap::del(<T&> key) +{ + <T><C>SplayNode* t = (<T><C>SplayNode*)(seek(key)); + if (t == 0) return; + + <T><C>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 + { + <T><C>SplayNode* r = t->rt; + <T><C>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 <T><C>SplayMap::_kill(<T><C>SplayNode* t) +{ + if (t != 0) + { + _kill(t->lt); + _kill(t->rt); + delete t; + } +} + + +<T><C>SplayNode* <T><C>SplayMap::_copy(<T><C>SplayNode* t) +{ + if (t != 0) + { + <T><C>SplayNode* l = _copy(t->lt); + <T><C>SplayNode* r = _copy(t->rt); + <T><C>SplayNode* x = new <T><C>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 <T><C>SplayMap::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T><C>SplayNode* trail = leftmost(); + <T><C>SplayNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/SplayMap.hP b/gnu/lib/libg++/g++-include/gen/SplayMap.hP new file mode 100644 index 00000000000..39cbe12be5f --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayMap.hP @@ -0,0 +1,166 @@ +// 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 _<T><C>SplayMap_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>SplayMap_h 1 + +#include "<T>.<C>.Map.h" + +#ifndef _<T><C>SplayNode +#define _<T><C>SplayNode 1 + +struct <T><C>SplayNode +{ + <T><C>SplayNode* lt; + <T><C>SplayNode* rt; + <T><C>SplayNode* par; + <T> item; + <C> cont; + <T><C>SplayNode(<T&> h, <C&> c, + <T><C>SplayNode* l=0, + <T><C>SplayNode* r=0); + ~<T><C>SplayNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>SplayNode::<T><C>SplayNode(<T&> h, <C&> c, + <T><C>SplayNode* l, + <T><C>SplayNode* r) + :item(h), cont(c), lt(l), rt(r), par(0) {} + +inline <T><C>SplayNode::~<T><C>SplayNode() {} + +#endif + +typedef <T><C>SplayNode* <T><C>SplayNodePtr; + +#endif + +class <T><C>SplayMap : public <T><C>Map +{ +protected: + <T><C>SplayNode* root; + + <T><C>SplayNode* leftmost(); + <T><C>SplayNode* rightmost(); + <T><C>SplayNode* pred(<T><C>SplayNode* t); + <T><C>SplayNode* succ(<T><C>SplayNode* t); + void _kill(<T><C>SplayNode* t); + <T><C>SplayNode* _copy(<T><C>SplayNode* t); + +public: + <T><C>SplayMap(<C&> dflt); + <T><C>SplayMap(<T><C>SplayMap& a); + ~<T><C>SplayMap(); + + <C>& operator [] (<T&> key); + + void del(<T&> key); + + Pix first(); + void next(Pix& i); + <T>& key(Pix i); + <C>& contents(Pix i); + + Pix seek(<T&> key); + int contains(<T&> key); + + void clear(); + + Pix last(); + void prev(Pix& i); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>SplayMap::~<T><C>SplayMap() +{ + _kill(root); +} + +inline <T><C>SplayMap::<T><C>SplayMap(<C&> dflt) :(dflt) +{ + root = 0; +} + +inline <T><C>SplayMap::<T><C>SplayMap(<T><C>SplayMap& b) :(b.def) +{ + count = b.count; + root = _copy(b.root); +} + +inline Pix <T><C>SplayMap::first() +{ + return Pix(leftmost()); +} + +inline Pix <T><C>SplayMap::last() +{ + return Pix(rightmost()); +} + +inline void <T><C>SplayMap::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T><C>SplayNode*)i)); +} + +inline void <T><C>SplayMap::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T><C>SplayNode*)i)); +} + +inline <T>& <T><C>SplayMap::key (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>SplayNode*)i)->item; +} + +inline <C>& <T><C>SplayMap::contents (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T><C>SplayNode*)i)->cont; +} + +inline void <T><C>SplayMap::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T><C>SplayMap::contains(<T&> key) +{ + return seek(key) != 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SplayPQ.ccP b/gnu/lib/libg++/g++-include/gen/SplayPQ.ccP new file mode 100644 index 00000000000..cfb8ab46c56 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayPQ.ccP @@ -0,0 +1,529 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.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 +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; +} _dummy_null; + + +/* + traversal primitives +*/ + + +<T>SplayNode* <T>SplayPQ::leftmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T>SplayNode* <T>SplayPQ::rightmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T>SplayNode* <T>SplayPQ::succ(<T>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; + } + } +} + +<T>SplayNode* <T>SplayPQ::pred(<T>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 <T>SplayPQ::seek(<T&> key) +{ + <T>SplayNode* t = root; + if (t == 0) + return 0; + + int comp = <T>CMP(key, t->item); + if (comp == 0) + return Pix(t); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + break; + else + { + comp = <T>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 = <T>CMP(key, t->item); + } + } + } + else + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + break; + else + { + comp = <T>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 = <T>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 <T>SplayPQ::enq(<T&> item) +{ + ++count; + <T>SplayNode* newnode = new <T>SplayNode(item); + <T>SplayNode* t = root; + if (t == 0) + { + root = newnode; + return Pix(root); + } + + int comp = <T>CMP(item, t->item); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + int done = 0; + while (!done) + { + if (comp >= 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + { + tr = newnode; + comp = 0; done = 1; + } + else + comp = <T>CMP(item, tr->item); + + if (comp <= 0) + { + l->rt = t; t->par = l; + l = t; + t = tr; + } + else + { + <T>SplayNode* trr = tr->rt; + if (trr == 0) + { + trr = newnode; + comp = 0; done = 1; + } + else + comp = <T>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 + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + { + tl = newnode; + comp = 0; done = 1; + } + else + comp = <T>CMP(item, tl->item); + + if (comp >= 0) + { + r->lt = t; t->par = r; + r = t; + t = tl; + } + else + { + <T>SplayNode* tll = tl->lt; + if (tll == 0) + { + tll = newnode; + comp = 0; done = 1; + } + else + comp = <T>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 <T>SplayPQ::del(Pix pix) +{ + <T>SplayNode* t = (<T>SplayNode*)pix; + if (t == 0) return; + + <T>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 + { + <T>SplayNode* r = t->rt; + <T>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; +} + +<T>& <T>SplayPQ::front() +{ + if (root == 0) + error ("min: empty tree\n"); +// else + { + <T>SplayNode* t = root; + <T>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 <T>SplayPQ::del_front() +{ + if (root != 0) + { + --count; + <T>SplayNode* t = root; + <T>SplayNode* l = root->lt; + if (l == 0) + { + if ((root = t->rt) != 0) root->par = 0; + delete t; + } + else + { + for(;;) + { + <T>SplayNode* ll = l->lt; + if (ll == 0) + { + if ((t->lt = l->rt) != 0) t->lt->par = t; + delete l; + break; + } + else + { + <T>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; + } + } + } + } + } +} + +<T> <T>SplayPQ::deq() +{ + if (root == 0) + error("deq: empty tree"); +// else + { + --count; + <T>SplayNode* t = root; + <T>SplayNode* l = root->lt; + if (l == 0) + { + if ((root = t->rt) != 0) root->par = 0; + <T> res = t->item; + delete t; + return res; + } + else + { + for(;;) + { + <T>SplayNode* ll = l->lt; + if (ll == 0) + { + if ((t->lt = l->rt) != 0) t->lt->par = t; + <T> res = l->item; + delete l; + return res; + } + else + { + <T>SplayNode* lll = ll->lt; + if (lll == 0) + { + if ((l->lt = ll->rt) != 0) l->lt->par = l; + <T> 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 <T>SplayPQ::_kill(<T>SplayNode* t) +{ + if (t != 0) + { + _kill(t->lt); + _kill(t->rt); + delete t; + } +} + + +<T>SplayNode* <T>SplayPQ::_copy(<T>SplayNode* t) +{ + if (t != 0) + { + <T>SplayNode* l = _copy(t->lt); + <T>SplayNode* r = _copy(t->rt); + <T>SplayNode* x = new <T>SplayNode(t->item, l, r); + if (l != 0) l->par = x; + if (r != 0) r->par = x; + return x; + } + else + return 0; +} + +int <T>SplayPQ::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T>SplayNode* trail = leftmost(); + <T>SplayNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/SplayPQ.hP b/gnu/lib/libg++/g++-include/gen/SplayPQ.hP new file mode 100644 index 00000000000..8c738256c4b --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplayPQ.hP @@ -0,0 +1,157 @@ +// 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 _<T>SplayPQ_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SplayPQ_h 1 + +#include "<T>.PQ.h" + +#ifndef _<T>SplayNode +#define _<T>SplayNode 1 + +struct <T>SplayNode +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; + <T> item; + <T>SplayNode(<T&> h, <T>SplayNode* l=0, <T>SplayNode* r=0); + ~<T>SplayNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplayNode::<T>SplayNode(<T&> h, <T>SplayNode* l, <T>SplayNode* r) +:item(h), lt(l), rt(r), par(0) {} + +inline <T>SplayNode::~<T>SplayNode() {} + +#endif + +typedef <T>SplayNode* <T>SplayNodePtr; + +#endif + +class <T>SplayPQ : public <T>PQ +{ +protected: + <T>SplayNode* root; + + <T>SplayNode* leftmost(); + <T>SplayNode* rightmost(); + <T>SplayNode* pred(<T>SplayNode* t); + <T>SplayNode* succ(<T>SplayNode* t); + void _kill(<T>SplayNode* t); + <T>SplayNode* _copy(<T>SplayNode* t); + +public: + <T>SplayPQ(); + <T>SplayPQ(<T>SplayPQ& a); + ~<T>SplayPQ(); + + Pix enq(<T&> item); + <T> deq(); + + <T>& front(); + void del_front(); + + int contains(<T&> item); + + void clear(); + + Pix first(); + Pix last(); + void next(Pix& i); + void prev(Pix& i); + <T>& operator () (Pix i); + void del(Pix i); + Pix seek(<T&> item); + + int OK(); // rep invariant +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplayPQ::~<T>SplayPQ() +{ + _kill(root); +} + +inline <T>SplayPQ::<T>SplayPQ() +{ + root = 0; + count = 0; +} + +inline <T>SplayPQ::<T>SplayPQ(<T>SplayPQ& b) +{ + count = b.count; + root = _copy(b.root); +} + +inline Pix <T>SplayPQ::first() +{ + return Pix(leftmost()); +} + +inline Pix <T>SplayPQ::last() +{ + return Pix(rightmost()); +} + +inline void <T>SplayPQ::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T>SplayNode*)i)); +} + +inline void <T>SplayPQ::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T>SplayNode*)i)); +} + +inline <T>& <T>SplayPQ::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>SplayNode*)i)->item; +} + +inline void <T>SplayPQ::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T>SplayPQ::contains(<T&> key) +{ + return seek(key) != 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/SplaySet.ccP b/gnu/lib/libg++/g++-include/gen/SplaySet.ccP new file mode 100644 index 00000000000..fc037a0a0a7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplaySet.ccP @@ -0,0 +1,505 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include <assert.h> +#include "<T>.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 +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; +} _dummy_null; + + +/* + traversal primitives +*/ + + +<T>SplayNode* <T>SplaySet::leftmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->lt != 0) t = t->lt; + return t; +} + +<T>SplayNode* <T>SplaySet::rightmost() +{ + <T>SplayNode* t = root; + if (t != 0) while (t->rt != 0) t = t->rt; + return t; +} + +<T>SplayNode* <T>SplaySet::succ(<T>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; + } + } +} + +<T>SplayNode* <T>SplaySet::pred(<T>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 <T>SplaySet::seek(<T&> key) +{ + <T>SplayNode* t = root; + if (t == 0) + return 0; + + int comp = <T>CMP(key, t->item); + if (comp == 0) + return Pix(t); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + break; + else + { + comp = <T>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 = <T>CMP(key, t->item); + } + } + } + else + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + break; + else + { + comp = <T>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 = <T>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 <T>SplaySet::add(<T&> item) +{ + <T>SplayNode* t = root; + if (t == 0) + { + ++count; + root = new <T>SplayNode(item); + return Pix(root); + } + int comp = <T>CMP(item, t->item); + if (comp == 0) + return Pix(t); + + <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null); + <T>SplayNode* l = dummy; + <T>SplayNode* r = dummy; + dummy->rt = dummy->lt = dummy->par = 0; + + while (comp != 0) + { + if (comp > 0) + { + <T>SplayNode* tr = t->rt; + if (tr == 0) + { + ++count; + tr = new <T>SplayNode(item); + comp = 0; + } + else + comp = <T>CMP(item, tr->item); + + if (comp <= 0) + { + l->rt = t; t->par = l; + l = t; + t = tr; + } + else + { + <T>SplayNode* trr = tr->rt; + if (trr == 0) + { + ++count; + trr = new <T>SplayNode(item); + comp = 0; + } + else + comp = <T>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 + { + <T>SplayNode* tl = t->lt; + if (tl == 0) + { + ++count; + tl = new <T>SplayNode(item); + comp = 0; + } + else + comp = <T>CMP(item, tl->item); + + if (comp >= 0) + { + r->lt = t; t->par = r; + r = t; + t = tl; + } + else + { + <T>SplayNode* tll = tl->lt; + if (tll == 0) + { + ++count; + tll = new <T>SplayNode(item); + comp = 0; + } + else + comp = <T>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 <T>SplaySet::del(<T&> key) +{ + <T>SplayNode* t = (<T>SplayNode*)(seek(key)); + if (t == 0) return; + + <T>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 + { + <T>SplayNode* r = t->rt; + <T>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 <T>SplaySet::_kill(<T>SplayNode* t) +{ + if (t != 0) + { + _kill(t->lt); + _kill(t->rt); + delete t; + } +} + + +<T>SplayNode* <T>SplaySet::_copy(<T>SplayNode* t) +{ + if (t != 0) + { + <T>SplayNode* l = _copy(t->lt); + <T>SplayNode* r = _copy(t->rt); + <T>SplayNode* x = new <T>SplayNode(t->item, l, r); + if (l != 0) l->par = x; + if (r != 0) r->par = x; + return x; + } + else + return 0; +} + +/* relationals */ + +int <T>SplaySet::operator == (<T>SplaySet& y) +{ + if (count != y.count) + return 0; + else + { + <T>SplayNode* t = leftmost(); + <T>SplayNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (!<T>EQ(t->item, u->item)) + return 0; + else + { + t = succ(t); + u = y.succ(u); + } + } + } +} + +int <T>SplaySet::operator <= (<T>SplaySet& y) +{ + if (count > y.count) + return 0; + else + { + <T>SplayNode* t = leftmost(); + <T>SplayNode* u = y.leftmost(); + for (;;) + { + if (t == 0) + return 1; + else if (u == 0) + return 0; + int cmp = <T>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 <T>SplaySet::operator |=(<T>SplaySet& y) +{ + if (&y == this) return; + <T>SplayNode* u = y.leftmost(); + while (u != 0) + { + add(u->item); + u = y.succ(u); + } +} + +void <T>SplaySet::operator &= (<T>SplaySet& y) +{ + if (y.count == 0) + clear(); + else if (&y != this && count != 0) + { + <T>SplayNode* t = leftmost(); + while (t != 0) + { + <T>SplayNode* s = succ(t); + if (y.seek(t->item) == 0) del(t->item); + t = s; + } + } +} + + +void <T>SplaySet::operator -=(<T>SplaySet& y) +{ + if (&y == this) + clear(); + else if (y.count != 0) + { + <T>SplayNode* t = leftmost(); + while (t != 0) + { + <T>SplayNode* s = succ(t); + if (y.seek(t->item) != 0) del(t->item); + t = s; + } + } +} + +int <T>SplaySet::OK() +{ + int v = 1; + if (root == 0) + v = count == 0; + else + { + int n = 1; + <T>SplayNode* trail = leftmost(); + <T>SplayNode* t = succ(trail); + while (t != 0) + { + ++n; + v &= <T>CMP(trail->item, t->item) < 0; + trail = t; + t = succ(t); + } + v &= n == count; + } + if (!v) error("invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/g++-include/gen/SplaySet.hP b/gnu/lib/libg++/g++-include/gen/SplaySet.hP new file mode 100644 index 00000000000..b499fdc45ef --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/SplaySet.hP @@ -0,0 +1,167 @@ +// 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 _<T>SplaySet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>SplaySet_h 1 + +#include "<T>.Set.h" + +#ifndef _<T>SplayNode +#define _<T>SplayNode 1 + +struct <T>SplayNode +{ + <T>SplayNode* lt; + <T>SplayNode* rt; + <T>SplayNode* par; + <T> item; + <T>SplayNode(<T&> h, <T>SplayNode* l=0, <T>SplayNode* r=0); + ~<T>SplayNode(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplayNode::<T>SplayNode(<T&> h, <T>SplayNode* l, <T>SplayNode* r) +:item(h), lt(l), rt(r), par(0) {} + +inline <T>SplayNode::~<T>SplayNode() {} + +#endif + +typedef <T>SplayNode* <T>SplayNodePtr; + +#endif + +class <T>SplaySet : public <T>Set +{ +protected: + <T>SplayNode* root; + + <T>SplayNode* leftmost(); + <T>SplayNode* rightmost(); + <T>SplayNode* pred(<T>SplayNode* t); + <T>SplayNode* succ(<T>SplayNode* t); + void _kill(<T>SplayNode* t); + <T>SplayNode* _copy(<T>SplayNode* t); + +public: + <T>SplaySet(); + <T>SplaySet(<T>SplaySet& a); + ~<T>SplaySet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item); + + Pix last(); + void prev(Pix& i); + + void operator |= (<T>SplaySet& b); + void operator -= (<T>SplaySet& b); + void operator &= (<T>SplaySet& b); + + int operator == (<T>SplaySet& b); + int operator != (<T>SplaySet& b); + int operator <= (<T>SplaySet& b); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>SplaySet::~<T>SplaySet() +{ + _kill(root); +} + +inline <T>SplaySet::<T>SplaySet() +{ + root = 0; + count = 0; +} + +inline <T>SplaySet::<T>SplaySet(<T>SplaySet& b) +{ + count = b.count; + root = _copy(b.root); +} + + +inline int <T>SplaySet::operator != (<T>SplaySet& b) +{ + return ! (*this == b); +} + +inline Pix <T>SplaySet::first() +{ + return Pix(leftmost()); +} + +inline Pix <T>SplaySet::last() +{ + return Pix(rightmost()); +} + +inline void <T>SplaySet::next(Pix& i) +{ + if (i != 0) i = Pix(succ((<T>SplayNode*)i)); +} + +inline void <T>SplaySet::prev(Pix& i) +{ + if (i != 0) i = Pix(pred((<T>SplayNode*)i)); +} + +inline <T>& <T>SplaySet::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return ((<T>SplayNode*)i)->item; +} + +inline void <T>SplaySet::clear() +{ + _kill(root); + count = 0; + root = 0; +} + +inline int <T>SplaySet::contains(<T&> key) +{ + return seek(key) != 0; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Stack.ccP b/gnu/lib/libg++/g++-include/gen/Stack.ccP new file mode 100644 index 00000000000..efb6b8edbde --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Stack.ccP @@ -0,0 +1,11 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.Stack.h" + +<T>Stack::~<T>Stack() {} + +void <T>Stack::error(const char* msg) +{ + (*lib_error_handler)("Stack", msg); +} diff --git a/gnu/lib/libg++/g++-include/gen/Stack.hP b/gnu/lib/libg++/g++-include/gen/Stack.hP new file mode 100644 index 00000000000..46c4799f45b --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Stack.hP @@ -0,0 +1,62 @@ +// 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 _<T>Stack_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Stack_h + +#include <builtin.h> + +#include "<T>.defs.h" + +class <T>Stack +{ +public: + <T>Stack(); + virtual ~<T>Stack(); + + virtual void push(<T&> item) = 0; + virtual <T> pop() = 0; + virtual <T>& 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; +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) +inline <T>Stack::<T>Stack() {} +#endif + + +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VHBag.ccP b/gnu/lib/libg++/g++-include/gen/VHBag.ccP new file mode 100644 index 00000000000..d56643df9f5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHBag.ccP @@ -0,0 +1,269 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.VHBag.h" + +/* codes for status fields */ + +#define EMPTYCELL 0 +#define VALIDCELL 1 +#define DELETEDCELL 2 + + +<T>VHBag::<T>VHBag(unsigned int sz) +{ + tab = new <T>[size = sz]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +<T>VHBag::<T>VHBag(<T>VHBag& a) +{ + tab = new <T>[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) +{ + unsigned int dh = ((h / s) % s); + return (dh > 1)? dh : 1; +} + +Pix <T>VHBag::seek(<T&> key, Pix p) +{ + <T>* t = (<T>*) p; + if (t == 0 || !<T>EQ(*t, key)) + { + unsigned int hashval = <T>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 && <T>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 = <T>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 && <T>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 <T>VHBag::nof(<T&> item) +{ + int n = 0; + unsigned int hashval = <T>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 && <T>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 <T>VHBag::add(<T&> item) +{ + if (size <= count + 1) + resize(); + unsigned int bestspot = size; + unsigned int hashval = <T>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 <T>VHBag::del(<T&> key) +{ + unsigned int hashval = <T>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 && <T>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 <T>VHBag::remove(<T&> key) +{ + unsigned int hashval = <T>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 && <T>EQ(key, tab[h])) + { + status[h] = DELETEDCELL; + --count; + } + if (i == 0) + h = (h + doublehashinc(hashval, size)) % size; + else if (++h >= size) + h -= size; + } +} + +void <T>VHBag::clear() +{ + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +void <T>VHBag::resize(unsigned int newsize) +{ + if (newsize <= count) + { + newsize = DEFAULT_INITIAL_CAPACITY; + while (newsize <= count) newsize <<= 1; + } + <T>* oldtab = tab; + char* oldstatus = status; + unsigned int oldsize = size; + tab = new <T>[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 <T>VHBag::first() +{ + for (unsigned int pos = 0; pos < size; ++pos) + if (status[pos] == VALIDCELL) return Pix(&tab[pos]); + return 0; +} + +void <T>VHBag::next(Pix& i) +{ + if (i == 0) return; + unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1; + for (; pos < size; ++pos) + if (status[pos] == VALIDCELL) + { + i = Pix(&tab[pos]); + return; + } + i = 0; +} + + +int <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/VHBag.hP b/gnu/lib/libg++/g++-include/gen/VHBag.hP new file mode 100644 index 00000000000..b88673c9f01 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHBag.hP @@ -0,0 +1,92 @@ +// 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 _<T>VHBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>VHBag_h 1 + +#include "<T>.Bag.h" + + +class <T>VHBag : public <T>Bag +{ +protected: + <T>* tab; + char* status; + unsigned int size; + +public: + <T>VHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY); + <T>VHBag(<T>VHBag& a); + ~<T>VHBag(); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int nof(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item, Pix from = 0); + + int capacity(); + void resize(unsigned int newsize = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>VHBag::~<T>VHBag() +{ + delete [size] tab; + delete status; +} + + +inline int <T>VHBag::capacity() +{ + return size; +} + +inline int <T>VHBag::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T>VHBag::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return *((<T>*)i); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VHMap.ccP b/gnu/lib/libg++/g++-include/gen/VHMap.ccP new file mode 100644 index 00000000000..b6129446606 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHMap.ccP @@ -0,0 +1,215 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.<C>.VHMap.h" + +/* codes for status fields */ + +#define EMPTYCELL 0 +#define VALIDCELL 1 +#define DELETEDCELL 2 + + +<T><C>VHMap::<T><C>VHMap(<C&> dflt, unsigned int sz) + :<T><C>Map(dflt) +{ + tab = new <T>[size = sz]; + cont = new <C>[size]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; +} + +<T><C>VHMap::<T><C>VHMap(<T><C>VHMap& a) : <T><C>Map(a.def) +{ + tab = new <T>[size = a.size]; + cont = new <C>[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) +{ + unsigned int dh = ((h / s) % s); + return (dh > 1)? dh : 1; +} + +Pix <T><C>VHMap::seek(<T&> key) +{ + unsigned int hashval = <T>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 && <T>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; +} + + +<C>& <T><C>VHMap::operator [](<T&> item) +{ + if (size <= count + 1) + resize(); + + unsigned int bestspot = size; + unsigned int hashval = <T>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 (<T>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 <T><C>VHMap::del(<T&> key) +{ + unsigned int hashval = <T>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 && <T>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 <T><C>VHMap::clear() +{ + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +void <T><C>VHMap::resize(unsigned int newsize) +{ + if (newsize <= count) + { + newsize = DEFAULT_INITIAL_CAPACITY; + while (newsize <= count) newsize <<= 1; + } + <T>* oldtab = tab; + <C>* oldcont = cont; + char* oldstatus = status; + unsigned int oldsize = size; + tab = new <T>[size = newsize]; + cont = new <C>[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 <T><C>VHMap::first() +{ + for (unsigned int pos = 0; pos < size; ++pos) + if (status[pos] == VALIDCELL) return Pix(&tab[pos]); + return 0; +} + +void <T><C>VHMap::next(Pix& i) +{ + if (i == 0) return; + unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1; + for (; pos < size; ++pos) + if (status[pos] == VALIDCELL) + { + i = Pix(&tab[pos]); + return; + } + i = 0; +} + + +int <T><C>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/VHMap.hP b/gnu/lib/libg++/g++-include/gen/VHMap.hP new file mode 100644 index 00000000000..b0b1ecc08a8 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHMap.hP @@ -0,0 +1,94 @@ +// 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 _<T><C>VHMap_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T><C>VHMap_h 1 + +#include "<T>.<C>.Map.h" + + +class <T><C>VHMap : public <T><C>Map +{ +protected: + <T>* tab; + <C>* cont; + char* status; + unsigned int size; + +public: + <T><C>VHMap(<C&> dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY); + <T><C>VHMap(<T><C>VHMap& a); + ~<T><C>VHMap(); + + <C>& operator [] (<T&> key); + + void del(<T&> key); + + Pix first(); + void next(Pix& i); + <T>& key(Pix i); + <C>& contents(Pix i); + + Pix seek(<T&> key); + int contains(<T&> key); + + void clear(); + void resize(unsigned int newsize = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T><C>VHMap::~<T><C>VHMap() +{ + delete [size] tab; + delete [size] cont; + delete [size] status; +} + +inline int <T><C>VHMap::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T><C>VHMap::key(Pix i) +{ + if (i == 0) error("null Pix"); + return *((<T>*)i); +} + +inline <C>& <T><C>VHMap::contents(Pix i) +{ + if (i == 0) error("null Pix"); + return cont[((unsigned)(i) - (unsigned)(tab)) / sizeof(<T>)]; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VHSet.ccP b/gnu/lib/libg++/g++-include/gen/VHSet.ccP new file mode 100644 index 00000000000..f93f1354cc4 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHSet.ccP @@ -0,0 +1,268 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.VHSet.h" + +/* codes for status fields */ + +#define EMPTYCELL 0 +#define VALIDCELL 1 +#define DELETEDCELL 2 + + +<T>VHSet::<T>VHSet(unsigned int sz) +{ + tab = new <T>[size = sz]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +<T>VHSet::<T>VHSet(<T>VHSet& a) +{ + tab = new <T>[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) +{ + unsigned int dh = ((h / s) % s); + return (dh > 1)? dh : 1; +} + +Pix <T>VHSet::seek(<T&> key) +{ + unsigned int hashval = <T>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 && <T>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 <T>VHSet::add(<T&> item) +{ + if (size <= count + 1) + resize(); + + unsigned int bestspot = size; + unsigned int hashval = <T>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 (<T>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 <T>VHSet::del(<T&> key) +{ + unsigned int hashval = <T>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 && <T>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 <T>VHSet::clear() +{ + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +void <T>VHSet::resize(unsigned int newsize) +{ + if (newsize <= count) + { + newsize = DEFAULT_INITIAL_CAPACITY; + while (newsize <= count) newsize <<= 1; + } + <T>* oldtab = tab; + char* oldstatus = status; + unsigned int oldsize = size; + tab = new <T>[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 <T>VHSet::first() +{ + for (unsigned int pos = 0; pos < size; ++pos) + if (status[pos] == VALIDCELL) return Pix(&tab[pos]); + return 0; +} + +void <T>VHSet::next(Pix& i) +{ + if (i == 0) return; + unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1; + for (; pos < size; ++pos) + if (status[pos] == VALIDCELL) + { + i = Pix(&tab[pos]); + return; + } + i = 0; +} + +int <T>VHSet:: operator == (<T>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 <T>VHSet::operator <= (<T>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 <T>VHSet::operator |= (<T>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 <T>VHSet::operator &= (<T>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 <T>VHSet::operator -= (<T>VHSet& b) +{ + for (unsigned int i = 0; i < size; ++i) + { + if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) + { + status[i] = DELETEDCELL; + --count; + } + } +} + +int <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/VHSet.hP b/gnu/lib/libg++/g++-include/gen/VHSet.hP new file mode 100644 index 00000000000..3ec4d5253fb --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHSet.hP @@ -0,0 +1,105 @@ +// 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 _<T>VHSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>VHSet_h 1 + +#include "<T>.Set.h" + + + +class <T>VHSet : public <T>Set +{ +protected: + <T>* tab; + char* status; + unsigned int size; + +public: + <T>VHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY); + <T>VHSet(<T>VHSet& a); + ~<T>VHSet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item); + + void operator |= (<T>VHSet& b); + void operator -= (<T>VHSet& b); + void operator &= (<T>VHSet& b); + + int operator == (<T>VHSet& b); + int operator != (<T>VHSet& b); + int operator <= (<T>VHSet& b); + + int capacity(); + void resize(unsigned int newsize = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>VHSet::~<T>VHSet() +{ + delete [size] tab; + delete status; +} + + +inline int <T>VHSet::capacity() +{ + return size; +} + +inline int <T>VHSet::contains(<T&> key) +{ + return seek(key) != 0; +} + +inline <T>& <T>VHSet::operator () (Pix i) +{ + if (i == 0) error("null Pix"); + return *((<T>*)i); +} + +inline int <T>VHSet::operator != (<T>VHSet& b) +{ + return ! ((*this) == b); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VOHSet.ccP b/gnu/lib/libg++/g++-include/gen/VOHSet.ccP new file mode 100644 index 00000000000..382e1e96fc7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VOHSet.ccP @@ -0,0 +1,313 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.VOHSet.h" + + +/* codes for status fields */ +#define EMPTYCELL 0 +#define VALIDCELL 1 +#define DELETEDCELL 2 + + +<T>VOHSet::<T>VOHSet(int sz) +{ +// 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 <T>[size]; + status = new char[size]; + for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = cnt = 0; +} + +<T>VOHSet::<T>VOHSet(<T>VOHSet& a) +{ + tab = new <T>[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 <T>VOHSet::seek(<T&> 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 = <T>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 = <T>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 <T>VOHSet::add(<T&> x) +{ + if (size <= cnt+1) + resize(); + + unsigned hashval = <T>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 = <T>CMP(x, tab[h]); + if (cmp == 0) + return Pix(&tab[h]); + + <T> item = x; + Pix mypix = 0; + unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1)); + + for (;;) + { + if (cmp < 0) + { + <T> temp = tab[h]; + tab[h] = item; + item = temp; + if (mypix == 0) mypix = Pix(&tab[h]); + inc = ((((<T>HASH(item) / size) << 1) + 1) & (size - 1)); + h = ((h + inc) & (size - 1)); + cmp = <T>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 <T>VOHSet::del(<T&> 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 = <T>HASH(key); + unsigned h = hashval & (size - 1); + unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1)); + + while (status[h] != EMPTYCELL) + { + int cmp = <T>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 <T>VOHSet::clear() +{ + for (int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = cnt = 0; +} + +void <T>VOHSet::resize(int newsize) +{ + if (newsize <= count) + newsize = count; + int s = 1; + while (s <= newsize) s <<= 1; + newsize = s; + + <T>* oldtab = tab; + char* oldstatus = status; + int oldsize = size; + tab = new <T>[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 <T>VOHSet::first() +{ + for (int pos = 0; pos < size; ++pos) + if (status[pos] == VALIDCELL) return Pix(&tab[pos]); + return 0; +} + +void <T>VOHSet::next(Pix& i) +{ + if (i == 0) return; + int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1; + for (; pos < size; ++pos) + if (status[pos] == VALIDCELL) + { + i = Pix(&tab[pos]); + return; + } + i = 0; +} + + +int <T>VOHSet:: operator == (<T>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 <T>VOHSet:: operator != (<T>VOHSet& b) +{ + return !(*this == b); +} + +int <T>VOHSet::operator <= (<T>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 <T>VOHSet::operator |= (<T>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 <T>VOHSet::operator &= (<T>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 <T>VOHSet::operator -= (<T>VOHSet& b) +{ + for (int i = 0; i < size; ++i) + { + if (status[i] == VALIDCELL && b.seek(tab[i]) != 0) + { + status[i] = DELETEDCELL; + --count; + } + } +} + +int <T>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; +} + + + diff --git a/gnu/lib/libg++/g++-include/gen/VOHSet.hP b/gnu/lib/libg++/g++-include/gen/VOHSet.hP new file mode 100644 index 00000000000..6c71288044c --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VOHSet.hP @@ -0,0 +1,97 @@ +// 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 _<T>VOHSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>VOHSet_h 1 + +#include "<T>.Set.h" + + + +class <T>VOHSet : public <T>Set +{ + <T>* tab; + char* status; + int size; + int cnt; // keeps track of VALIDCELLs and DELETEDCELLs + +public: + <T>VOHSet(int sz = DEFAULT_INITIAL_CAPACITY); + <T>VOHSet(<T>VOHSet&); + ~<T>VOHSet(); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + Pix seek(<T&> item); + + void operator |= (<T>VOHSet& b); + void operator -= (<T>VOHSet& b); + void operator &= (<T>VOHSet& b); + + int operator == (<T>VOHSet& b); + int operator != (<T>VOHSet& b); + int operator <= (<T>VOHSet& b); + + int capacity(); + void resize(int newsize = 0); + + int OK(); +}; + + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>VOHSet::~<T>VOHSet() +{ + delete [size] tab; + delete status; +} + + +inline int <T>VOHSet::contains(int key) +{ + return seek(key) != 0; +} + + +inline <T>& <T>VOHSet::operator () (Pix p) +{ + if (p == 0) error("null Pix"); + return *((<T>*)p); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VQueue.ccP b/gnu/lib/libg++/g++-include/gen/VQueue.ccP new file mode 100644 index 00000000000..7ffab10d9ba --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VQueue.ccP @@ -0,0 +1,88 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.VQueue.h" + +<T>VQueue::<T>VQueue(<T>VQueue& b) +:size(b.size), cnt(b.cnt), inp(b.inp), outp(b.outp), s(new <T> [b.size]) +{ + int j = outp; + for (int i = 0; i < cnt; ++i) + { + s[j] = b.s[j]; + if (++j == size) j = 0; + } +} + +void <T>VQueue::operator = (<T>VQueue& b) +{ + if (&b == this) return; + if (size != b.size) + { + delete [size] s; + s = new <T> [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 <T>VQueue::resize(int newsz) +{ + if (newsz < cnt) + error("resize: new size too small"); + <T>* news = new <T> [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 <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/VQueue.hP b/gnu/lib/libg++/g++-include/gen/VQueue.hP new file mode 100644 index 00000000000..66f58d84e02 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VQueue.hP @@ -0,0 +1,139 @@ +// 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 _<T>VQueue_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>VQueue_h 1 + +#include "<T>.Queue.h" + +class <T>VQueue : public <T>Queue +{ +protected: + int size; + int cnt; + int inp; + int outp; + <T>* s; + +public: + + <T>VQueue(int sz = DEFAULT_INITIAL_CAPACITY); + <T>VQueue(<T>VQueue&); + ~<T>VQueue(); + + void operator = (<T>VQueue&); + + void enq(<T&> item); + <T> deq(); + <T>& front(); + void del_front(); + + int length(); + int empty(); + int full(); + + int capacity(); + void resize(int sz); + void clear(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>VQueue::<T>VQueue(int sz) +{ + s = new <T> [size = sz]; + cnt = inp = outp = 0; +} + +inline <T>VQueue::~<T>VQueue() +{ + delete [size] s; +} + +inline void <T>VQueue::clear() +{ + inp = outp = 0; + cnt = 0; +} + +inline int <T>VQueue::empty() +{ + return cnt <= 0; +} + +inline int <T>VQueue::capacity() +{ + return size; +} + +inline int <T>VQueue::full() +{ + return cnt >= size; +} + +inline int <T>VQueue::length() +{ + return cnt; +} + +inline void <T>VQueue::enq(<T&> item) +{ + if (cnt >= size) error("enq to full Queue."); + ++cnt; + s[inp] = item; + if (++inp == size) inp = 0; +} + +inline <T> <T>VQueue::deq() +{ + if (cnt <= 0) error("deq from empty Queue."); + --cnt; + int i = outp; + if (++outp == size) outp = 0; + return s[i]; +} + + +inline void <T>VQueue::del_front() +{ + if (cnt <= 0) error("delete from empty Queue."); + --cnt; + if (++outp == size) outp = 0; +} + +inline <T>& <T>VQueue::front() +{ + if (empty()) error("top from empty Queue."); + return s[outp]; +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/VStack.ccP b/gnu/lib/libg++/g++-include/gen/VStack.ccP new file mode 100644 index 00000000000..0404aa3b0c8 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VStack.ccP @@ -0,0 +1,71 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.VStack.h" + +// error handling + + +<T>VStack::<T>VStack(<T>VStack& b) +:size(b.size), ptr(b.ptr), s(new <T> [b.size]) +{ + for (int i = 0; i < ptr; ++i) s[i] = b.s[i]; +} + +void <T>VStack::operator = (<T>VStack& b) +{ + if (&b == this) return; + if (size < b.ptr) + { + delete [size] s; + s = new <T> [b.size]; + size = b.size; + } + ptr = b.ptr; + for (int i = 0; i < ptr; ++i) s[i] = b.s[i]; +} + + +void <T>VStack::resize(int newsz) +{ + if (newsz < ptr) error("resize: new size too small"); + <T>* news = new <T> [newsz]; + for (int i = 0; i < ptr; ++i) news[i] = s[i]; + delete [size] s; + s = news; + size = newsz; +} + +int <T>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; +} diff --git a/gnu/lib/libg++/g++-include/gen/VStack.hP b/gnu/lib/libg++/g++-include/gen/VStack.hP new file mode 100644 index 00000000000..c41bcba9214 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VStack.hP @@ -0,0 +1,128 @@ +// 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 _<T>VStack_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>VStack_h 1 + +#include "<T>.Stack.h" + +class <T>VStack : public <T>Stack +{ +protected: + int size; + int ptr; + <T>* s; + +public: + + <T>VStack(int sz = DEFAULT_INITIAL_CAPACITY); + <T>VStack(<T>VStack&); + ~<T>VStack(); + + void operator = (<T>VStack&); + void push(<T&> item); + <T> pop(); + <T>& top(); + void del_top(); + + int length(); + int empty(); + int full(); + void clear(); + + void resize(int sz); + int capacity(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>VStack::<T>VStack(int sz) +{ + s = new <T> [size = sz]; + ptr = 0; +} + +inline <T>VStack::~<T>VStack() +{ + delete [size] s; +} + +inline void <T>VStack::clear() +{ + ptr = 0; +} + +inline int <T>VStack::capacity() +{ + return size; +} + +inline int <T>VStack::empty() +{ + return ptr == 0; +} + +inline int <T>VStack::full() +{ + return ptr == size; +} + +inline int <T>VStack::length() +{ + return ptr; +} + +inline void <T>VStack::push(<T&> item) +{ + if (full()) error("push to full stack."); + s[ptr++] = item; +} + +inline <T> <T>VStack::pop() +{ + if (empty()) error("pop from empty stack."); + return s[--ptr]; +} + + +inline void <T>VStack::del_top() +{ + if (empty()) error("del_top from empty stack."); + --ptr; +} + +inline <T>& <T>VStack::top() +{ + if (empty()) error("top from empty stack."); + return s[ptr-1]; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/Vec.ccP b/gnu/lib/libg++/g++-include/gen/Vec.ccP new file mode 100644 index 00000000000..381b7d6a176 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Vec.ccP @@ -0,0 +1,474 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <stream.h> +#include "<T>.Vec.h" + +// error handling + + +void default_<T>Vec_error_handler(const char* msg) +{ + cerr << "Fatal <T>Vec error. " << msg << "\n"; + exit(1); +} + +one_arg_error_handler_t <T>Vec_error_handler = default_<T>Vec_error_handler; + +one_arg_error_handler_t set_<T>Vec_error_handler(one_arg_error_handler_t f) +{ + one_arg_error_handler_t old = <T>Vec_error_handler; + <T>Vec_error_handler = f; + return old; +} + +void <T>Vec::error(const char* msg) +{ + (*<T>Vec_error_handler)(msg); +} + +void <T>Vec::range_error() +{ + (*<T>Vec_error_handler)("Index out of range."); +} + +<T>Vec::<T>Vec(<T>Vec& v) +{ + s = new <T> [len = v.len]; + <T>* top = &(s[len]); + <T>* t = s; + <T>* u = v.s; + while (t < top) *t++ = *u++; +} + +<T>Vec::<T>Vec(int l, <T&> fill_value) +{ + s = new <T> [len = l]; + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) *t++ = fill_value; +} + + +<T>Vec& <T>Vec::operator = (<T>Vec& v) +{ + if (this != &v) + { + delete[len] s; + s = new <T> [len = v.len]; + <T>* top = &(s[len]); + <T>* t = s; + <T>* u = v.s; + while (t < top) *t++ = *u++; + } + return *this; +} + +void <T>Vec::apply(<T>Procedure f) +{ + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) (*f)(*t++); +} + +// can't just realloc since there may be need for constructors/destructors +void <T>Vec::resize(int newl) +{ + <T>* news = new <T> [newl]; + <T>* p = news; + int minl = (len < newl)? len : newl; + <T>* top = &(s[minl]); + <T>* t = s; + while (t < top) *p++ = *t++; + delete [len] s; + s = news; + len = newl; +} + +<T>Vec concat(<T>Vec & a, <T>Vec & b) +{ + int newl = a.len + b.len; + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* top = &(a.s[a.len]); + <T>* t = a.s; + while (t < top) *p++ = *t++; + top = &(b.s[b.len]); + t = b.s; + while (t < top) *p++ = *t++; + return <T>Vec(newl, news); +} + + +<T>Vec combine(<T>Combiner f, <T>Vec& a, <T>Vec& b) +{ + int newl = (a.len < b.len)? a.len : b.len; + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* top = &(a.s[newl]); + <T>* t = a.s; + <T>* u = b.s; + while (t < top) *p++ = (*f)(*t++, *u++); + return <T>Vec(newl, news); +} + +<T> <T>Vec::reduce(<T>Combiner f, <T&> base) +{ + <T> r = base; + <T>* top = &(s[len]); + <T>* t = s; + while (t < top) r = (*f)(r, *t++); + return r; +} + +<T>Vec reverse(<T>Vec& a) +{ + <T>* news = new <T> [a.len]; + if (a.len != 0) + { + <T>* lo = news; + <T>* hi = &(news[a.len - 1]); + while (lo < hi) + { + <T> tmp = *lo; + *lo++ = *hi; + *hi-- = tmp; + } + } + return <T>Vec(a.len, news); +} + +void <T>Vec::reverse() +{ + if (len != 0) + { + <T>* lo = s; + <T>* hi = &(s[len - 1]); + while (lo < hi) + { + <T> tmp = *lo; + *lo++ = *hi; + *hi-- = tmp; + } + } +} + +int <T>Vec::index(<T&> targ) +{ + for (int i = 0; i < len; ++i) if (targ == s[i]) return i; + return -1; +} + +<T>Vec map(<T>Mapper f, <T>Vec& a) +{ + <T>* news = new <T> [a.len]; + <T>* p = news; + <T>* top = &(a.s[a.len]); + <T>* t = a.s; + while(t < top) *p++ = (*f)(*t++); + return <T>Vec(a.len, news); +} + +int operator == (<T>Vec& a, <T>Vec& b) +{ + if (a.len != b.len) + return 0; + <T>* top = &(a.s[a.len]); + <T>* t = a.s; + <T>* u = b.s; + while (t < top) if (*t++ != *u++) return 0; + return 1; +} + +void <T>Vec::fill(<T&> val, int from, int n) +{ + int to; + if (n < 0) + to = len - 1; + else + to = from + n - 1; + if ((unsigned)from > to) + range_error(); + <T>* t = &(s[from]); + <T>* top = &(s[to]); + while (t <= top) *t++ = val; +} + +<T>Vec <T>Vec::at(int from, int n) +{ + int to; + if (n < 0) + { + n = len - from; + to = len - 1; + } + else + to = from + n - 1; + if ((unsigned)from > to) + range_error(); + <T>* news = new <T> [n]; + <T>* p = news; + <T>* t = &(s[from]); + <T>* top = &(s[to]); + while (t <= top) *p++ = *t++; + return <T>Vec(n, news); +} + +<T>Vec merge(<T>Vec & a, <T>Vec & b, <T>Comparator f) +{ + int newl = a.len + b.len; + <T>* news = new <T> [newl]; + <T>* p = news; + <T>* topa = &(a.s[a.len]); + <T>* as = a.s; + <T>* topb = &(b.s[b.len]); + <T>* 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 <T>Vec(newl, news); +} + +static int gsort(<T>*, int, <T>Comparator); + +void <T>Vec::sort (<T>Comparator compar) +{ + gsort(s, len, compar); +} + + +// An adaptation og Schmidt's new quicksort + +static inline void SWAP(<T>* A, <T>* B) +{ + <T> tmp = *A; *A = *B; *B = tmp; +} + +/* This should be replaced by a standard ANSI macro. */ +#define BYTES_PER_WORD 8 +#define BYTES_PER_LONG 4 + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ + +#define STACK_SIZE (BYTES_PER_WORD * BYTES_PER_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 (<T> *base_ptr, int total_elems, <T>Comparator cmp) +{ +/* Stack node declarations used to store unfulfilled partition obligations. */ + struct stack_node { <T> *lo; <T> *hi; }; + <T> pivot_buffer; + int max_thresh = MAX_THRESH; + + if (total_elems > MAX_THRESH) + { + <T> *lo = base_ptr; + <T> *hi = lo + (total_elems - 1); + <T> *left_ptr; + <T> *right_ptr; + stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */ + stack_node *top = stack + 1; + + while (STACK_NOT_EMPTY) + { + { + <T> *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. */ + + <T> *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!). */ + + + { + <T> *end_ptr = base_ptr + 1 * (total_elems - 1); + <T> *run_ptr; + <T> *tmp_ptr = base_ptr; + <T> *thresh = (end_ptr < (base_ptr + max_thresh))? + end_ptr : (base_ptr + max_thresh); + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr += 1) + if ((*cmp) (*run_ptr, *tmp_ptr) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + SWAP (tmp_ptr, base_ptr); + + /* Insertion sort, running from left-hand-side up to `right-hand-side.' + Pretty much straight out of the original GNU qsort routine. */ + + for (run_ptr = base_ptr + 1; (tmp_ptr = run_ptr += 1) <= end_ptr; ) + { + + while ((*cmp) (*run_ptr, *(tmp_ptr -= 1)) < 0) + ; + + if ((tmp_ptr += 1) != run_ptr) + { + <T> *trav; + + for (trav = run_ptr + 1; --trav >= run_ptr;) + { + <T> c = *trav; + <T> *hi, *lo; + + for (hi = lo = trav; (lo -= 1) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + + } + } + return 1; +} diff --git a/gnu/lib/libg++/g++-include/gen/Vec.hP b/gnu/lib/libg++/g++-include/gen/Vec.hP new file mode 100644 index 00000000000..8addfd6c19c --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/Vec.hP @@ -0,0 +1,142 @@ +// 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 _<T>Vec_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>Vec_h 1 + +#ifndef _<T>_typedefs +#define _<T>_typedefs 1 +typedef void (*<T>Procedure)(<T&>); +typedef <T> (*<T>Mapper)(<T&>); +typedef <T> (*<T>Combiner)(<T&>, <T&>); +typedef int (*<T>Predicate)(<T&>); +typedef int (*<T>Comparator)(<T&>, <T&>); +#endif + + +class <T>Vec +{ +protected: + int len; + <T> *s; + + <T>Vec(int l, <T>* d); +public: + <T>Vec (); + <T>Vec (int l); + <T>Vec (int l, <T&> fill_value); + <T>Vec (<T>Vec&); + ~<T>Vec (); + + <T>Vec & operator = (<T>Vec & a); + <T>Vec at(int from = 0, int n = -1); + + int capacity(); + void resize(int newlen); + + <T>& operator [] (int n); + <T>& elem(int n); + + friend <T>Vec concat(<T>Vec & a, <T>Vec & b); + friend <T>Vec map(<T>Mapper f, <T>Vec & a); + friend <T>Vec merge(<T>Vec & a, <T>Vec & b, <T>Comparator f); + friend <T>Vec combine(<T>Combiner f, <T>Vec & a, <T>Vec & b); + friend <T>Vec reverse(<T>Vec & a); + + void reverse(); + void sort(<T>Comparator f); + void fill(<T&> val, int from = 0, int n = -1); + + void apply(<T>Procedure f); + <T> reduce(<T>Combiner f, <T&> base); + int index(<T&> targ); + + friend int operator == (<T>Vec& a, <T>Vec& b); + friend int operator != (<T>Vec& a, <T>Vec& b); + + void error(const char* msg); + void range_error(); +}; + +extern void default_<T>Vec_error_handler(const char*); +extern one_arg_error_handler_t <T>Vec_error_handler; + +extern one_arg_error_handler_t + set_<T>Vec_error_handler(one_arg_error_handler_t f); + + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>Vec::<T>Vec() +{ + len = 0; s = 0; +} + +inline <T>Vec::<T>Vec(int l) +{ + s = new <T> [len = l]; +} + + +inline <T>Vec::<T>Vec(int l, <T>* d) :len(l), s(d) {} + + +inline <T>Vec::~<T>Vec() +{ + delete[len] s; +} + + +inline <T>& <T>Vec::operator [] (int n) +{ + if ((unsigned)n >= len) + range_error(); + return s[n]; +} + +inline <T>& <T>Vec::elem(int n) +{ + return s[n]; +} + + +inline int <T>Vec::capacity() +{ + return len; +} + + + +inline int operator != (<T>Vec& a, <T>Vec& b) +{ + return !(a == b); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPBag.ccP b/gnu/lib/libg++/g++-include/gen/XPBag.ccP new file mode 100644 index 00000000000..59fa706b7a9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPBag.ccP @@ -0,0 +1,77 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPBag.h" + +int <T>XPBag::OK() +{ + int v = p.OK(); + v &= count == p.length(); + if (!v) error("invariant failure"); + return v; +} + +Pix <T>XPBag::seek(<T&> item, Pix i) +{ + if (i == 0) i = p.first(); else next(i); + for (; i != 0; p.next(i)) if (<T>EQ(p(i), item)) return i; + return 0; +} + +int <T>XPBag::nof(<T&> item) +{ + int n = 0; + for (int i = p.low(); i < p.fence(); p.next(i)) if (<T>EQ(p[i], item)) ++n; + return n; +} + +void <T>XPBag::del(<T&> item) +{ + for (int i = p.low(); i < p.fence(); p.next(i)) + { + if (<T>EQ(p[i], item)) + { + --count; + p[i] = p.low_element(); + p.del_low(); + return; + } + } +} + +void <T>XPBag::remove(<T&> item) +{ + for (int i = p.low(); i < p.fence(); p.next(i)) + { + if (<T>EQ(p[i], item)) + { + --count; + p[i] = p.low_element(); + p.del_low(); + } + } +} + diff --git a/gnu/lib/libg++/g++-include/gen/XPBag.hP b/gnu/lib/libg++/g++-include/gen/XPBag.hP new file mode 100644 index 00000000000..4e8aad719fc --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPBag.hP @@ -0,0 +1,105 @@ +// 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 _<T>XPBag_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPBag_h 1 + +#include "<T>.Bag.h" +#include "<T>.XPlex.h" + +class <T>XPBag : public <T>Bag +{ +protected: + <T>XPlex p; + +public: + <T>XPBag(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPBag(const <T>XPBag&); + + Pix add(<T&> item); + void del(<T&> item); + void remove(<T&>item); + int nof(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item, Pix from = 0); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPBag::<T>XPBag(int chunksize) + : p(chunksize) { count = 0; } + +inline <T>XPBag::<T>XPBag(const <T>XPBag& s) : p(s.p) { count = s.count; } + +inline Pix <T>XPBag::first() +{ + return p.first(); +} + +inline void <T>XPBag::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>XPBag::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>XPBag::clear() +{ + count = 0; p.clear(); +} + +inline int <T>XPBag::owns (Pix idx) +{ + return p.owns(idx); +} + +inline Pix <T>XPBag::add(<T&> item) +{ + ++count; + return p.index_to_Pix(p.add_high(item)); +} + +inline int <T>XPBag::contains(<T&> item) +{ + return seek(item) != 0; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPDeque.ccP b/gnu/lib/libg++/g++-include/gen/XPDeque.ccP new file mode 100644 index 00000000000..6b363d9bdc4 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPDeque.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPDeque.h" diff --git a/gnu/lib/libg++/g++-include/gen/XPDeque.hP b/gnu/lib/libg++/g++-include/gen/XPDeque.hP new file mode 100644 index 00000000000..528766a8cef --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPDeque.hP @@ -0,0 +1,142 @@ +// 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 _<T>XPDeque_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPDeque_h + +#include "<T>.XPlex.h" +#include "<T>.Deque.h" + +class <T>XPDeque : public <T>Deque +{ + <T>XPlex p; + +public: + <T>XPDeque(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPDeque(const <T>XPDeque& d); + ~<T>XPDeque(); + + void operator = (const <T>XPDeque&); + + void push(<T&> item); // insert at front + void enq(<T&> item); // insert at rear + + <T>& front(); + <T>& rear(); + + <T> deq(); + void del_front(); + void del_rear(); + + void clear(); + int empty(); + int full(); + int length(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPDeque::<T>XPDeque(int chunksize) + : p(chunksize) {} +inline <T>XPDeque::<T>XPDeque(const <T>XPDeque& d) : p(d.p) {} + +inline <T>XPDeque::~<T>XPDeque() {} + +inline void <T>XPDeque::push(<T&>item) +{ + p.add_low(item); +} + +inline void <T>XPDeque::enq(<T&>item) +{ + p.add_high(item); +} + +inline <T> <T>XPDeque::deq() +{ + <T> res = p.low_element(); + p.del_low(); + return res; +} + +inline <T>& <T>XPDeque::front() +{ + return p.low_element(); +} + +inline <T>& <T>XPDeque::rear() +{ + return p.high_element(); +} + +inline void <T>XPDeque::del_front() +{ + p.del_low(); +} + +inline void <T>XPDeque::del_rear() +{ + p.del_high(); +} + +inline void <T>XPDeque::operator =(const <T>XPDeque& s) +{ + p.operator = (s.p); +} + + +inline int <T>XPDeque::empty() +{ + return p.empty(); +} + +inline int <T>XPDeque::full() +{ + return p.full(); +} + +inline int <T>XPDeque::length() +{ + return p.length(); +} + +inline int <T>XPDeque::OK() +{ + return p.OK(); +} + +inline void <T>XPDeque::clear() +{ + p.clear(); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPPQ.ccP b/gnu/lib/libg++/g++-include/gen/XPPQ.ccP new file mode 100644 index 00000000000..f11731dad43 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPPQ.ccP @@ -0,0 +1,148 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPPQ.h" + +int <T>XPPQ::OK() +{ + int v = p.OK(); + v &= p.low() == 1; + v &= count == p.length(); + if (!v) error("invariant failure"); + return v; +} + +Pix <T>XPPQ::seek(<T&> item) +{ + for (int i = p.low(); i < p.fence(); p.next(i)) + if (<T>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 <T>XPPQ::enq(<T&> item) +{ + p.add_high(item); + <T>* pk = &(p.high_element()); + int par = ++count >> 1; + while (par != 0) + { + <T>* ppar = &(p[par]); + if (!(<T>LE(*ppar, item))) + { + *pk = *ppar; + pk = ppar; + par >>= 1; + } + else + break; + } + *pk = item; + return Pix(pk); +} + +void <T>XPPQ::del_front() +{ + if (count == 0) error("empty PQ"); + --count; + <T>* pk = &(p.low_element()); + <T>* ph = &(p.high_element()); + int child = 2; + while (child <= count) + { + <T>* pchild = &(p[child]); + if (child < count) + { + <T>* prchild = &(p[child+1]); + if (!(<T>LE(*pchild, *prchild))) + { + pchild = prchild; + ++child; + } + } + if (!(<T>LE(*ph, *pchild))) + { + *pk = *pchild; + pk = pchild; + child <<= 1; + } + else + break; + } + *pk = *ph; + p.del_high(); +} + + +void <T>XPPQ::del(Pix i) +{ + if (i == 0) error("null Pix"); + --count; + int k = p.Pix_to_index(i); + <T>* pk = &(p[k]); + <T>* ph = &(p.high_element()); + int child = k << 1; + while (child <= count) + { + <T>* pchild = &(p[child]); + if (child < count) + { + <T>* prchild = &(p[child+1]); + if (!(<T>LE(*pchild, *prchild))) + { + pchild = prchild; + ++child; + } + } + if (!(<T>LE(*ph, *pchild))) + { + *pk = *pchild; + pk = pchild; + child <<= 1; + } + else + break; + } + int par = child >> 2; + while (par != 0) + { + <T>* ppar = &(p[par]); + if (!(<T>LE(*ppar, *ph))) + { + *pk = *ppar; + pk = ppar; + par >>= 1; + } + else + break; + } + *pk = *ph; + p.del_high(); +} + + diff --git a/gnu/lib/libg++/g++-include/gen/XPPQ.hP b/gnu/lib/libg++/g++-include/gen/XPPQ.hP new file mode 100644 index 00000000000..46cdfdb6e8d --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPPQ.hP @@ -0,0 +1,115 @@ +// 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 _<T>XPPQ_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPPQ_h 1 + +#include "<T>.PQ.h" +#include "<T>.XPlex.h" + +class <T>XPPQ : public <T>PQ +{ +protected: + <T>XPlex p; + +public: + <T>XPPQ(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPPQ(const <T>XPPQ&); + + Pix enq(<T&> item); + <T> deq(); + + <T>& front(); + void del_front(); + + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + void del(Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + int OK(); // rep invariant +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPPQ::<T>XPPQ(int chunksize) + : p(1, chunksize) { count = 0; } + +inline <T>XPPQ::<T>XPPQ(const <T>XPPQ& s) : p(s.p) { count = s.count; } + +inline Pix <T>XPPQ::first() +{ + return p.first(); +} + +inline void <T>XPPQ::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>XPPQ::operator ()(Pix idx) +{ + return p(idx); +} + +inline <T>& <T>XPPQ::front () +{ + return p.low_element(); +} + +inline <T> <T>XPPQ::deq () +{ + <T> x = p.low_element(); + del_front(); + return x; +} + +inline void <T>XPPQ::clear() +{ + count = 0; p.clear(); +} + +inline int <T>XPPQ::contains (<T&> item) +{ + return seek(item) != 0; +} + +inline int <T>XPPQ::owns (Pix idx) +{ + return p.owns(idx); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPQueue.ccP b/gnu/lib/libg++/g++-include/gen/XPQueue.ccP new file mode 100644 index 00000000000..77bfd1c7a95 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPQueue.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPQueue.h" diff --git a/gnu/lib/libg++/g++-include/gen/XPQueue.hP b/gnu/lib/libg++/g++-include/gen/XPQueue.hP new file mode 100644 index 00000000000..da070fd0458 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPQueue.hP @@ -0,0 +1,123 @@ +// 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 _<T>XPQueue_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPQueue_h + +#include "<T>.XPlex.h" +#include "<T>.Queue.h" + +class <T>XPQueue : public <T>Queue +{ +protected: + <T>XPlex p; + +public: + <T>XPQueue(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPQueue(const <T>XPQueue& q); + ~<T>XPQueue(); + + void operator = (const <T>XPQueue&); + + void enq(<T&> item); + <T> deq(); + <T>& front(); + void del_front(); + + void clear(); + int empty(); + int full(); + int length(); + + int OK(); +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPQueue::<T>XPQueue(int chunksize) + : p(chunksize) {} +inline <T>XPQueue::<T>XPQueue(const <T>XPQueue& q) : p(q.p) {} + +inline <T>XPQueue::~<T>XPQueue() {} + +inline void <T>XPQueue::enq(<T&>item) +{ + p.add_high(item); +} + +inline <T> <T>XPQueue::deq() +{ + <T> res = p.low_element(); + p.del_low(); + return res; +} + +inline <T>& <T>XPQueue::front() +{ + return p.low_element(); +} + + +inline void <T>XPQueue::del_front() +{ + p.del_low(); +} + +inline void <T>XPQueue::operator =(const <T>XPQueue& s) +{ + p.operator = (s.p); +} + +inline int <T>XPQueue::empty() +{ + return p.empty(); +} + +inline int <T>XPQueue::full() +{ + return p.full(); +} + +inline int <T>XPQueue::length() +{ + return p.length(); +} + +inline int <T>XPQueue::OK() +{ + return p.OK(); +} + +inline void <T>XPQueue::clear() +{ + p.clear(); +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPSet.ccP b/gnu/lib/libg++/g++-include/gen/XPSet.ccP new file mode 100644 index 00000000000..97743735635 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPSet.ccP @@ -0,0 +1,68 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPSet.h" + +int <T>XPSet::OK() +{ + int v = p.OK(); + v &= count == p.length(); + if (!v) error("invariant failure"); + return v; +} + +Pix <T>XPSet::seek(<T&> item) +{ + for (int i = p.low(); i < p.fence(); p.next(i)) + if (<T>EQ(p[i],item)) return p.index_to_Pix(i); + return 0; +} + +Pix <T>XPSet::add(<T&> item) +{ + Pix i = seek(item); + if (i == 0) + { + ++count; + i = p.index_to_Pix(p.add_high(item)); + } + return i; +} + +void <T>XPSet::del(<T&> item) +{ + for (int i = p.low(); i < p.fence(); p.next(i)) + { + if (<T>EQ(p[i], item)) + { + --count; + p[i] = p.low_element(); + p.del_low(); + return; + } + } +} + diff --git a/gnu/lib/libg++/g++-include/gen/XPSet.hP b/gnu/lib/libg++/g++-include/gen/XPSet.hP new file mode 100644 index 00000000000..5e06b81d25d --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPSet.hP @@ -0,0 +1,99 @@ +// 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 _<T>XPSet_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPSet_h 1 + +#include "<T>.Set.h" +#include "<T>.XPlex.h" + +class <T>XPSet : public <T>Set +{ +protected: + <T>XPlex p; + +public: + <T>XPSet(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPSet(const <T>XPSet&); + + Pix add(<T&> item); + void del(<T&> item); + int contains(<T&> item); + + void clear(); + + Pix first(); + void next(Pix& i); + <T>& operator () (Pix i); + int owns(Pix i); + Pix seek(<T&> item); + + int OK(); +}; + + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPSet::<T>XPSet(int chunksize) + : p(chunksize) { count = 0; } + +inline <T>XPSet::<T>XPSet(const <T>XPSet& s) : p(s.p) { count = s.count; } + +inline Pix <T>XPSet::first() +{ + return p.first(); +} + +inline void <T>XPSet::next(Pix & idx) +{ + p.next(idx); +} + +inline <T>& <T>XPSet::operator ()(Pix idx) +{ + return p(idx); +} + +inline void <T>XPSet::clear() +{ + count = 0; p.clear(); +} + +inline int <T>XPSet::contains (<T&> item) +{ + return seek(item) != 0; +} + +inline int <T>XPSet::owns (Pix idx) +{ + return p.owns(idx); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPStack.ccP b/gnu/lib/libg++/g++-include/gen/XPStack.ccP new file mode 100644 index 00000000000..fe24f0f044a --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPStack.ccP @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPStack.h" diff --git a/gnu/lib/libg++/g++-include/gen/XPStack.hP b/gnu/lib/libg++/g++-include/gen/XPStack.hP new file mode 100644 index 00000000000..f0c18491e09 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPStack.hP @@ -0,0 +1,124 @@ +// 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 _<T>XPStack_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPStack_h + +#include "<T>.XPlex.h" +#include "<T>.Stack.h" + +class <T>XPStack : public <T>Stack +{ + <T>XPlex p; + +public: + <T>XPStack(int chunksize = DEFAULT_INITIAL_CAPACITY); + <T>XPStack(const <T>XPStack& s); + ~<T>XPStack(); + + void operator = (const <T>XPStack&); + + void push(<T&> item); + <T> pop(); + <T>& top(); + void del_top(); + + int empty(); + int full(); + int length(); + + void clear(); + + int OK(); + +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline <T>XPStack::<T>XPStack(int chunksize) + : p(chunksize) {} +inline <T>XPStack::<T>XPStack(const <T>XPStack& s) : p(s.p) {} + +inline <T>XPStack::~<T>XPStack() {} + +inline void <T>XPStack::push(<T&>item) +{ + p.add_high(item); +} + +inline <T> <T>XPStack::pop() +{ + <T> res = p.high_element(); + p.del_high(); + return res; +} + +inline <T>& <T>XPStack::top() +{ + return p.high_element(); +} + +inline void <T>XPStack::del_top() +{ + p.del_high(); +} + +inline void <T>XPStack::operator =(const <T>XPStack& s) +{ + p.operator = (s.p); +} + +inline int <T>XPStack::empty() +{ + return p.empty(); +} + +inline int <T>XPStack::full() +{ + return p.full(); +} + +inline int <T>XPStack::length() +{ + return p.length(); +} + +inline int <T>XPStack::OK() +{ + return p.OK(); +} + +inline void <T>XPStack::clear() +{ + p.clear(); +} + + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/XPlex.ccP b/gnu/lib/libg++/g++-include/gen/XPlex.ccP new file mode 100644 index 00000000000..2cef5293aa7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPlex.ccP @@ -0,0 +1,412 @@ +// 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.XPlex.h" + + +<T>XPlex:: <T>XPlex() +{ + lo = fnc = 0; + csize = DEFAULT_INITIAL_CAPACITY; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, lo, lo, fnc, lo+csize)); + hd = ch; +} + +<T>XPlex:: <T>XPlex(int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + lo = fnc = 0; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, lo, lo, fnc, csize)); + hd = ch; + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, chunksize, lo, fnc, fnc)); + hd = ch; + } +} + + +<T>XPlex:: <T>XPlex(int l, int chunksize) +{ + if (chunksize == 0) error("invalid constructor specification"); + lo = fnc = l; + if (chunksize > 0) + { + csize = chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, lo, lo, fnc, csize+lo)); + hd = ch; + } + else + { + csize = -chunksize; + <T>* data = new <T>[csize]; + set_cache(new <T>IChunk(data, chunksize+lo, lo, fnc, fnc)); + hd = ch; + } +} + +void <T>XPlex::make_initial_chunks(int up) +{ + int need = fnc - lo; + hd = 0; + if (up) + { + int l = lo; + do + { + int sz; + if (need >= csize) + sz = csize; + else + sz = need; + <T>* data = new <T> [csize]; + <T>IChunk* h = new <T>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; + <T>* data = new <T> [csize]; + <T>IChunk* h = new <T>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); +} + +<T>XPlex:: <T>XPlex(int l, int hi, const <T&> initval, int chunksize) +{ + 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); +} + +<T>XPlex::<T>XPlex(const <T>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 <T>XPlex::operator= (const <T>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 <T>XPlex::cache(int idx) const +{ + const <T>IChunk* tail = tl(); + const <T>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 <T>XPlex::cache(const <T>* p) const +{ + const <T>IChunk* old = ch; + const <T>IChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = (t->next()); + if (t == old) index_error(); + } + set_cache(t); +} + +int <T>XPlex::owns(Pix px) const +{ + <T>* p = (<T>*)px; + const <T>IChunk* old = ch; + const <T>IChunk* t = ch; + while (!t->actual_pointer(p)) + { + t = (t->next()); + if (t == old) { set_cache(t); return 0; } + } + set_cache(t); + return 1; +} + + +<T>* <T>XPlex::dosucc(const <T>* p) const +{ + if (p == 0) return 0; + const <T>IChunk* old = ch; + const <T>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)); +} + +<T>* <T>XPlex::dopred(const <T>* p) const +{ + if (p == 0) return 0; + const <T>IChunk* old = ch; + const <T>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 <T>XPlex::add_high(const <T&> elem) +{ + <T>IChunk* t = tl(); + if (!t->can_grow_high()) + { + if (t-><T>IChunk::empty() && one_chunk()) + t->clear(fnc); + else + { + <T>* data = new <T> [csize]; + t = (new <T>IChunk(data, fnc, fnc, fnc,fnc+csize)); + t->link_to_prev(tl()); + } + } + *((t-><T>IChunk::grow_high())) = elem; + set_cache(t); + return fnc++; +} + +int <T>XPlex::del_high () +{ + if (empty()) empty_error(); + <T>IChunk* t = tl(); + t-><T>IChunk::shrink_high(); + if (t-><T>IChunk::empty() && !one_chunk()) + { + <T>IChunk* pred = t->prev(); + del_chunk(t); + t = pred; + } + set_cache(t); + return --fnc - 1; +} + +int <T>XPlex::add_low (const <T&> elem) +{ + <T>IChunk* t = hd; + if (!t->can_grow_low()) + { + if (t-><T>IChunk::empty() && one_chunk()) + t->cleardown(lo); + else + { + <T>* data = new <T> [csize]; + hd = new <T>IChunk(data, lo-csize, lo, lo, lo); + hd->link_to_next(t); + t = hd; + } + } + *((t-><T>IChunk::grow_low())) = elem; + set_cache(t); + return --lo; +} + + +int <T>XPlex::del_low () +{ + if (empty()) empty_error(); + <T>IChunk* t = hd; + t-><T>IChunk::shrink_low(); + if (t-><T>IChunk::empty() && !one_chunk()) + { + hd = t->next(); + del_chunk(t); + t = hd; + } + set_cache(t); + return ++lo; +} + +void <T>XPlex::append (const <T>XPlex& a) +{ + for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]); +} + +void <T>XPlex::prepend (const <T>XPlex& a) +{ + for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]); +} + +void <T>XPlex::reverse() +{ + <T> tmp; + int l = lo; + int h = fnc - 1; + <T>IChunk* loch = hd; + <T>IChunk* hich = tl(); + while (l < h) + { + <T>* lptr = loch->pointer_to(l); + <T>* 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 <T>XPlex::fill(const <T&> x) +{ + for (int i = lo; i < fnc; ++i) (*this)[i] = x; +} + +void <T>XPlex::fill(const <T&> x, int l, int hi) +{ + for (int i = l; i <= hi; ++i) (*this)[i] = x; +} + + +void <T>XPlex::clear() +{ + if (fnc != lo) + { + <T>IChunk* t = tl(); + while (t != hd) + { + <T>IChunk* prv = t->prev(); + del_chunk(t); + t = prv; + } + t-><T>IChunk::clear(lo); + set_cache(t); + fnc = lo; + } +} + + +int <T>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))-><T>IChunk::low_index(); // first lo == plex lo + +// loop for others: + int found_ch = 0; // to make sure ch is in list; + const <T>IChunk* t = (hd); + for (;;) + { + if (t == ch) ++found_ch; + v &= t-><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; +} diff --git a/gnu/lib/libg++/g++-include/gen/XPlex.hP b/gnu/lib/libg++/g++-include/gen/XPlex.hP new file mode 100644 index 00000000000..41acef7fff7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/XPlex.hP @@ -0,0 +1,248 @@ +// 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 _<T>XPlex_h +#ifdef __GNUG__ +#pragma once +#pragma interface +#endif +#define _<T>XPlex_h 1 + +#include "<T>.Plex.h" + +class <T>XPlex: public <T>Plex +{ + <T>IChunk* ch; // cached chunk + + void make_initial_chunks(int up = 1); + + void cache(int idx) const; + void cache(const <T>* p) const; + + <T>* dopred(const <T>* p) const; + <T>* dosucc(const <T>* p) const; + + void set_cache(const <T>IChunk* t) const; // logically, + // not physically const +public: + <T>XPlex(); // set low = 0; + // fence = 0; + // csize = default + + <T>XPlex(int ch_size); // low = 0; + // fence = 0; + // csize = ch_size + + <T>XPlex(int lo, // low = lo; + int ch_size); // fence=lo + // csize = ch_size + + <T>XPlex(int lo, // low = lo + int hi, // fence = hi+1 + const <T&> initval,// fill with initval, + int ch_size = 0); // csize= ch_size + // or fence-lo if 0 + + <T>XPlex(const <T>XPlex&); + + void operator= (const <T>XPlex&); + +// virtuals + + + <T>& high_element (); + <T>& low_element (); + + const <T>& high_element () const; + const <T>& low_element () const; + + Pix first() const; + Pix last() const; + void prev(Pix& ptr) const; + void next(Pix& ptr) const; + int owns(Pix p) const; + <T>& operator () (Pix p); + const <T>& 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; + <T>& operator [] (int index); + const <T>& 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 <T&> elem); + int del_high (); + int add_low (const <T&> elem); + int del_low (); + + void fill(const <T&> x); + void fill(const <T&> x, int from, int to); + void clear(); + void reverse(); + void append(const <T>XPlex& a); + void prepend(const <T>XPlex& a); + + int OK () const; + +}; + +#if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) + +inline void <T>XPlex::prev(int& idx) const +{ + --idx; +} + +inline void <T>XPlex::next(int& idx) const +{ + ++idx; +} + +inline int <T>XPlex::full () const +{ + return 0; +} + +inline int <T>XPlex::can_add_high() const +{ + return 1; +} + +inline int <T>XPlex::can_add_low() const +{ + return 1; +} + +inline int <T>XPlex::valid (int idx) const +{ + return idx >= lo && idx < fnc; +} + +inline int <T>XPlex::low() const +{ + return lo; +} + +inline int <T>XPlex::high() const +{ + return fnc - 1; +} + +inline <T>& <T>XPlex:: operator [] (int idx) +{ + if (!ch->actual_index(idx)) cache(idx); + return *(ch->pointer_to(idx)); +} + +inline const <T>& <T>XPlex:: operator [] (int idx) const +{ + if (!ch->actual_index(idx)) cache(idx); + return *((const <T>*)(ch->pointer_to(idx))); +} + +inline <T>& <T>XPlex::low_element () +{ + if (empty()) index_error(); + return *(hd->pointer_to(lo)); +} + +inline const <T>& <T>XPlex::low_element () const +{ + if (empty()) index_error(); + return *((const <T>*)(hd->pointer_to(lo))); +} + +inline <T>& <T>XPlex::high_element () +{ + if (empty()) index_error(); + return *(tl()->pointer_to(fnc - 1)); +} + +inline const <T>& <T>XPlex::high_element () const +{ + if (empty()) index_error(); + return *((const <T>*)(tl()->pointer_to(fnc - 1))); +} + +inline int <T>XPlex::Pix_to_index(Pix px) const +{ + <T>* p = (<T>*)px; + if (!ch->actual_pointer(p)) cache(p); + return ch->index_of(p); +} + +inline Pix <T>XPlex::index_to_Pix(int idx) const +{ + if (!ch->actual_index(idx)) cache(idx); + return (Pix)(ch->pointer_to(idx)); +} + +inline Pix <T>XPlex::first() const +{ + return Pix(hd-><T>IChunk::first_pointer()); +} + +inline Pix <T>XPlex::last() const +{ + return Pix(tl()-><T>IChunk::last_pointer()); +} + +inline void <T>XPlex::prev(Pix& p) const +{ + Pix q = Pix(ch-><T>IChunk::pred((<T>*) p)); + p = (q == 0)? Pix(dopred((const <T>*) p)) : q; +} + +inline void <T>XPlex::next(Pix& p) const +{ + Pix q = Pix(ch-><T>IChunk::succ((<T>*) p)); + p = (q == 0)? Pix(dosucc((const <T>*)p)) : q; +} + +inline <T>& <T>XPlex:: operator () (Pix p) +{ + return *((<T>*)p); +} + +inline const <T>& <T>XPlex:: operator () (Pix p) const +{ + return *((const <T>*)p); +} + +inline void <T>XPlex::set_cache(const <T>IChunk* t) const +{ + ((<T>XPlex*)(this))->ch = (<T>IChunk*)t; +} + +#endif +#endif diff --git a/gnu/lib/libg++/g++-include/gen/defs.hP b/gnu/lib/libg++/g++-include/gen/defs.hP new file mode 100644 index 00000000000..4efc82d2632 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/defs.hP @@ -0,0 +1,60 @@ +// 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 _<T>defs_h +#ifdef __GNUG__ +#pragma once +#endif +#define _<T>defs_h 1 + + +// equality operator +#ifndef <T>EQ +#define <T>EQ(a, b) ((a) == (b)) +#endif + +// less-than-or-equal +#ifndef <T>LE +#define <T>LE(a, b) ((a) <= (b)) +#endif + +// comparison : less-than -> < 0; equal -> 0; greater-than -> > 0 +#ifndef <T>CMP +#define <T>CMP(a, b) ( ((a) <= (b))? (((a) == (b))? 0 : -1) : 1 ) +#endif + +// hash function +#ifndef <T>HASH +extern unsigned int hash(<T&>); +#define <T>HASH(x) hash(x) +#endif + +// initial capacity for structures requiring one + +#ifndef DEFAULT_INITIAL_CAPACITY +#define DEFAULT_INITIAL_CAPACITY 100 +#endif + + +#endif diff --git a/gnu/lib/libg++/g++-include/hash.cc b/gnu/lib/libg++/g++-include/hash.cc new file mode 100644 index 00000000000..4f16f975989 --- /dev/null +++ b/gnu/lib/libg++/g++-include/hash.cc @@ -0,0 +1,56 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> + +/* + 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; +} + diff --git a/gnu/lib/libg++/g++-include/ioob.cc b/gnu/lib/libg++/g++-include/ioob.cc new file mode 100644 index 00000000000..08409a5d292 --- /dev/null +++ b/gnu/lib/libg++/g++-include/ioob.cc @@ -0,0 +1,32 @@ +/* +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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Obstack.h> + +// Obstacks are used as an easy way to allocate enough space +// for various builtin input operations + + +Obstack _libgxx_io_ob; diff --git a/gnu/lib/libg++/g++-include/lg.cc b/gnu/lib/libg++/g++-include/lg.cc new file mode 100644 index 00000000000..b5ea5fd0fb9 --- /dev/null +++ b/gnu/lib/libg++/g++-include/lg.cc @@ -0,0 +1,32 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> + +long lg(unsigned long x) +{ + long l = 0; + while (x > 1) + { + x = x >> 1; + ++l; + } + return l; +} diff --git a/gnu/lib/libg++/g++-include/math.cc b/gnu/lib/libg++/g++-include/math.cc new file mode 100644 index 00000000000..f1a0e52aba5 --- /dev/null +++ b/gnu/lib/libg++/g++-include/math.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <math.h> diff --git a/gnu/lib/libg++/g++-include/new.cc b/gnu/lib/libg++/g++-include/new.cc new file mode 100644 index 00000000000..7a707a6ee9d --- /dev/null +++ b/gnu/lib/libg++/g++-include/new.cc @@ -0,0 +1,31 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <new.h> + +#if 0 /* ndef NO_LIBGXX_MALLOC */ + +void* operator new(size_t n) +{ + return malloc (n); +} +#endif diff --git a/gnu/lib/libg++/g++-include/new.h b/gnu/lib/libg++/g++-include/new.h new file mode 100644 index 00000000000..414923319fd --- /dev/null +++ b/gnu/lib/libg++/g++-include/new.h @@ -0,0 +1,35 @@ +/* $Id: new.h,v 1.1 1995/10/18 08:38:19 deraadt Exp $ */ + +#ifndef _new_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _new_h 1 + +#include <stddef.h> +#include <std.h> + +#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 new_handler_t __new_handler; +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 +inline void *operator new(size_t size, void *ptr, size_t new_len) +{ + return realloc(ptr, new_len * size); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/osfcn.h b/gnu/lib/libg++/g++-include/osfcn.h new file mode 100644 index 00000000000..3a12d99b56c --- /dev/null +++ b/gnu/lib/libg++/g++-include/osfcn.h @@ -0,0 +1,17 @@ +/* $Id: osfcn.h,v 1.1 1995/10/18 08:38:19 deraadt Exp $ */ + +#ifndef OSFCN_H +#define OSFCN_H 1 + +#include <std.h> +#include <time.h> +#include <sys/types.h> +#if _G_HAVE_SYS_SOCKET +#include <sys/socket.h> +#endif +#if _G_HAVE_SYS_RESOURCE +#include <sys/resource.h> +#endif + + +#endif diff --git a/gnu/lib/libg++/g++-include/pow.cc b/gnu/lib/libg++/g++-include/pow.cc new file mode 100644 index 00000000000..b56a8b7d779 --- /dev/null +++ b/gnu/lib/libg++/g++-include/pow.cc @@ -0,0 +1,70 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <math.h> + +double pow(double x, long p) +{ + if (p == 0) + return 1.0; + else if (x == 0.0) + return 0.0; + else + { + if (p < 0) + { + p = -p; + x = 1.0 / x; + } + + double r = 1.0; + for(;;) + { + if (p & 1) + r *= x; + if ((p >>= 1) == 0) + return r; + else + x *= x; + } + } +} + +long pow(long x, long p) +{ + if (p == 0) + return 1; + else if (p < 0 || x == 0) + return 0; + else + { + long r = 1; + for(;;) + { + if (p & 1) + r *= x; + if ((p >>= 1) == 0) + return r; + else + x *= x; + } + } +} diff --git a/gnu/lib/libg++/g++-include/regex.cc b/gnu/lib/libg++/g++-include/regex.cc new file mode 100644 index 00000000000..199308d0da2 --- /dev/null +++ b/gnu/lib/libg++/g++-include/regex.cc @@ -0,0 +1,2757 @@ +/* Extended regular expression matching and search library. + Copyright (C) 1985, 1989-90 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +// This is a translation into C++ of regex.c, the GNU regexp package. + +/* 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. + + On the other hand, if you compile with both -Dtest and -Dcanned you + can run some tests we've already thought of. */ + +/* AIX requires the alloca decl to be the first thing in the file. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#ifdef sparc +#include <alloca.h> +extern "C" void *__builtin_alloca(...); +#else +#ifdef _AIX +#pragma alloca +#else +char *alloca (); +#endif +#endif +#endif + +#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 <_G_config.h> +#include <string.h> +#include <stdlib.h> + +/* Define the syntax stuff, so we can do the \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#define SYNTAX(c) re_syntax_table[c] + + +#ifdef SYNTAX_TABLE + +char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +static char re_syntax_table[256]; + + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + memset (re_syntax_table, 0, 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 /* emacs */ + +/* We write fatal error messages on standard error. */ +#include <stdio.h> + +/* isalpha(3) etc. are used for the character classes. */ +#include <ctype.h> +/* Sequents are missing isgraph. */ +#ifndef isgraph +#define isgraph(c) (isprint((c)) && !isspace((c))) +#endif + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + + +/* 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 + whatsoever for its arguments. Zero-bytes may appear in the compiled + regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +enum regexpcode + { + unused=0, + exactn=1, /* Followed by one byte giving n, then by n literal bytes. */ + begline, /* Fail unless at beginning of line. */ + endline, /* Fail 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. Also + use it as an intermediary kind of jump when + compiling an or construct. */ + succeed_n, /* Used like on_failure_jump except has to succeed n times; + then gets turned into an on_failure_jump. The relative + address following it is useless until then. The + address is followed by two bytes containing n. */ + jump_n, /* Similar to jump, but jump n times only; also the relative + address following is in turn followed by yet two more bytes + containing n. */ + set_number_at, /* Set the following relative location to the + subsequent number. */ + anychar, /* Matches any (more or less) one character. */ + charset, /* Matches any one char belonging to specified set. + First following byte is number of bitmap bytes. + Then come bytes for a bitmap 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, /* Same parameters as charset, but match any character + that is not one of those specified. */ + start_memory, /* Start remembering the text that is matched, for + storing in a memory register. Followed by one + byte containing the register number. Register numbers + must be in the range 0 through RE_NREGS. */ + stop_memory, /* Stop remembering the text that is matched + and store it in a memory register. Followed by + one byte containing the register number. Register + numbers must be in the range 0 through RE_NREGS. */ + duplicate, /* Match a duplicate of something remembered. + Followed by one byte containing the index of the memory + register. */ +#ifdef emacs + before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ +#endif + 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. */ +#ifdef emacs + syntaxspec, /* Matches any character whose syntax is specified. + followed by a byte which contains a syntax code, + e.g., Sword. */ + notsyntaxspec /* Matches any character whose syntax differs from + that specified. */ +#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 + + +#ifndef SIGN_EXTEND_CHAR +#ifdef __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char)(c)) +#else +#define SIGN_EXTEND_CHAR(c) (((c)^128) - 128) /* As in Harbison and Steele. */ +#endif +#endif /* not SIGN_EXTEND_CHAR */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ +#define STORE_NUMBER(destination, number) \ + { (destination)[0] = (char)((number) & 0377); \ + (destination)[1] = (number) >> 8; } + +/* Same as STORE_NUMBER, except increment the destination pointer to + the byte after where the number is stored. Watch out that values for + DESTINATION such as p + 1 won't work, whereas p will. */ +#define STORE_NUMBER_AND_INCR(destination, number) \ + { STORE_NUMBER(destination, number); \ + (destination) += 2; } + + +/* Put into DESTINATION a number stored in two contingous bytes starting + at SOURCE. */ +#define EXTRACT_NUMBER(destination, source) \ + { (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*(char *)((source) + 1)) << 8; } + +/* Same as EXTRACT_NUMBER, except increment the pointer for source to + point to second byte of SOURCE. Note that SOURCE has to be a value + such as p, not, e.g., p + 1. */ +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + { EXTRACT_NUMBER (destination, source); \ + (source) += 2; } + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit-mask comprised of the various bits + defined in regex.h. */ + +int +re_set_syntax (int syntax) +{ + int ret; + + ret = obscure_syntax; + obscure_syntax = syntax; + return ret; +} + +/* Set by re_set_syntax to the current regexp syntax to recognize. */ +int obscure_syntax = 0; + + + +/* Macros for re_compile_pattern, which is found below these definitions. */ + +#define CHAR_CLASS_MAX_LENGTH 6 + +/* Fetch the next character in the uncompiled pattern, translating it if + necessary. */ +#define PATFETCH(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (const unsigned char *) p++; \ + if (translate) c = translate[c]; } + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (const unsigned char *) p++; } + +#define PATUNFETCH p-- + + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 28 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + { \ + while (b - bufp->buffer + (n) >= bufp->allocated) \ + EXTEND_BUFFER; \ + } + +/* Make sure we have one more byte of buffer space and then add CH to it. */ +#define BUFPUSH(ch) \ + { \ + GET_BUFFER_SPACE (1); \ + *b++ = (char) (ch); \ + } + +/* Extend the buffer by twice its current size via reallociation and + reset the pointers that pointed into the old allocation to point to + the correct places in the new allocation. If extending the buffer + results in it being larger than 1 << 16, then flag memory exhausted. */ +#define EXTEND_BUFFER \ + { char *old_buffer = bufp->buffer; \ + if (bufp->allocated == (1L<<16)) goto too_big; \ + bufp->allocated *= 2; \ + if (bufp->allocated > (1L<<16)) bufp->allocated = (1L<<16); \ + bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated); \ + if (bufp->buffer == 0) \ + goto memory_exhausted; \ + b = (b - old_buffer) + bufp->buffer; \ + if (fixup_jump) \ + fixup_jump = (fixup_jump - old_buffer) + bufp->buffer; \ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } + +/* Set the bit for character C in a character set list. */ +#define SET_LIST_BIT(c) (b[(c) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH)) + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (isdigit (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +/* Subroutines for re_compile_pattern. */ +static void store_jump (char *from, char opcode, char *to); +static void insert_jump (char op, char *from, char *to, char *current_end); +static void store_jump_n (char *from, char opcode, char *to, unsigned n); +static void insert_jump_n (char, char *, char *, char *, unsigned); +static void insert_op_2 (char, char *, char *_end, int, int); + + +/* 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. */ + +char * +re_compile_pattern (const char *pattern, int size, struct re_pattern_buffer *bufp) +{ + register char *b = bufp->buffer; + register const char *p = pattern; + const char *pend = pattern + size; + register unsigned c, c1; + const 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; + + /* In processing an interval, at least this many matches must be made. */ + int lower_bound; + + /* In processing an interval, at most this many matches can be made. */ + int upper_bound; + + /* Place in pattern (i.e., the {) to which to go back if the interval + is invalid. */ + const char *beg_interval = 0; + + /* 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. */ + + unsigned 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 = INIT_BUF_SIZE; + if (bufp->buffer) + /* EXTEND_BUFFER loses when bufp->allocated is 0. */ + bufp->buffer = (char *) realloc (bufp->buffer, INIT_BUF_SIZE); + else + /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = (char *) malloc (INIT_BUF_SIZE); + if (!bufp->buffer) goto memory_exhausted; + begalt = b = bufp->buffer; + } + + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '$': + { + const char *p1 = p; + /* When testing what follows the $, + look past the \-constructs that don't consume anything. */ + if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + while (p1 != pend) + { + if (*p1 == '\\' && p1 + 1 != pend + && (p1[1] == '<' || p1[1] == '>' + || p1[1] == '`' || p1[1] == '\'' +#ifdef emacs + || p1[1] == '=' +#endif + || p1[1] == 'b' || p1[1] == 'B')) + p1 += 2; + else + break; + } + if (obscure_syntax & RE_TIGHT_VBAR) + { + if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p1 != pend) + goto normal_char; + /* Make operand of last vbar end before this `$'. */ + if (fixup_jump) + store_jump (fixup_jump, jump, b); + fixup_jump = 0; + BUFPUSH (endline); + break; + } + /* $ means succeed if at end of line, but only in special contexts. + If validly in the middle of a pattern, it is a normal character. */ + + if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && p1 != pend) + goto invalid_pattern; + if (p1 == pend || *p1 == '\n' + || (obscure_syntax & RE_CONTEXT_INDEP_OPS) + || (obscure_syntax & RE_NO_BK_PARENS + ? *p1 == ')' + : *p1 == '\\' && p1[1] == ')') + || (obscure_syntax & RE_NO_BK_VBAR + ? *p1 == '|' + : *p1 == '\\' && p1[1] == '|')) + { + BUFPUSH (endline); + break; + } + goto normal_char; + } + case '^': + /* ^ means succeed if at beg of line, but only if no preceding + pattern. */ + + if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && laststart) + goto invalid_pattern; + if (laststart && p - 2 >= pattern && 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; + BUFPUSH (begline); + begalt = b; + } + else + BUFPUSH (begline); + break; + + case '+': + case '?': + if ((obscure_syntax & RE_BK_PLUS_QM) + || (obscure_syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern, char not special. */ + if (!laststart) + { + if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + /* If there is a sequence of repetition chars, + collapse it down 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 or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { + /* If more than one repetition is allowed, put in at the + end a backward relative jump from b to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). */ + GET_BUFFER_SPACE (3); + store_jump (b, maybe_finalize_jump, laststart - 3); + b += 3; /* Because store_jump put stuff here. */ + } + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + insert_jump (on_failure_jump, laststart, b + 3, b); + pending_exact = 0; + b += 3; + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + dummy-failure before the initial on-failure-jump + instruction of the loop. This effects a skip over that + instruction the first time we hit that loop. */ + GET_BUFFER_SPACE (6); + insert_jump (dummy_failure_jump, laststart, laststart + 6, b); + b += 3; + } + break; + + case '.': + laststart = b; + BUFPUSH (anychar); + break; + + case '[': + if (p == pend) + goto invalid_pattern; + while (b - bufp->buffer + > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH) + EXTEND_BUFFER; + + laststart = b; + if (*p == '^') + { + BUFPUSH (charset_not); + p++; + } + else + BUFPUSH (charset); + p1 = p; + + BUFPUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + /* Clear the whole map */ + memset (b, 0, (1 << BYTEWIDTH) / BYTEWIDTH); + + if ((obscure_syntax & RE_HAT_NOT_NEWLINE) && b[-2] == charset_not) + SET_LIST_BIT ('\n'); + + + /* Read in characters and ranges, setting map bits. */ + while (1) + { + /* Don't translate while fetching, in case it's a range bound. + When we set the bit for the character, we translate it. */ + PATFETCH_RAW (c); + + /* If set, \ escapes characters when inside [...]. */ + if ((obscure_syntax & RE_AWK_CLASS_HACK) && c == '\\') + { + PATFETCH(c1); + SET_LIST_BIT (c1); + continue; + } + if (c == ']') + { + if (p == p1 + 1) + { + /* If this is an empty bracket expression. */ + if ((obscure_syntax & RE_NO_EMPTY_BRACKETS) + && p == pend) + goto invalid_pattern; + } + else + /* Stop if this isn't merely a ] inside a bracket + expression, but rather the end of a bracket + expression. */ + break; + } + /* Get a range. */ + if (p[0] == '-' && p[1] != ']') + { + PATFETCH (c1); + /* Don't translate the range bounds while fetching them. */ + PATFETCH_RAW (c1); + + if ((obscure_syntax & RE_NO_EMPTY_RANGES) && c > c1) + goto invalid_pattern; + + if ((obscure_syntax & RE_NO_HYPHEN_RANGE_END) + && c1 == '-' && *p != ']') + goto invalid_pattern; + + while (c <= c1) + { + /* Translate each char that's in the range. */ + if (translate) + SET_LIST_BIT (translate[c]); + else + SET_LIST_BIT (c); + c++; + } + } + else if ((obscure_syntax & RE_CHAR_CLASSES) + && c == '[' && p[0] == ':') + { + /* Longest valid character class word has six characters. */ + char str[CHAR_CLASS_MAX_LENGTH]; + PATFETCH (c); + c1 = 0; + /* If no ] at end. */ + if (p == pend) + goto invalid_pattern; + while (1) + { + /* Don't translate the ``character class'' characters. */ + PATFETCH_RAW (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + if (p == pend + || c == ']' /* End of the bracket expression. */ + || p[0] != ']' + || p + 1 == pend + || (strcmp (str, "alpha") != 0 + && strcmp (str, "upper") != 0 + && strcmp (str, "lower") != 0 + && strcmp (str, "digit") != 0 + && strcmp (str, "alnum") != 0 + && strcmp (str, "xdigit") != 0 + && strcmp (str, "space") != 0 + && strcmp (str, "print") != 0 + && strcmp (str, "punct") != 0 + && strcmp (str, "graph") != 0 + && strcmp (str, "cntrl") != 0)) + { + /* Undo the ending character, the letters, and leave + the leading : and [ (but set bits for them). */ + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + } + else + { + /* The ] at the end of the character class. */ + PATFETCH (c); + if (c != ']') + goto invalid_pattern; + for (c = 0; c < (1 << BYTEWIDTH); c++) + { + if ((strcmp (str, "alpha") == 0 && isalpha (c)) + || (strcmp (str, "upper") == 0 && isupper (c)) + || (strcmp (str, "lower") == 0 && islower (c)) + || (strcmp (str, "digit") == 0 && isdigit (c)) + || (strcmp (str, "alnum") == 0 && isalnum (c)) + || (strcmp (str, "xdigit") == 0 && isxdigit (c)) + || (strcmp (str, "space") == 0 && isspace (c)) + || (strcmp (str, "print") == 0 && isprint (c)) + || (strcmp (str, "punct") == 0 && ispunct (c)) + || (strcmp (str, "graph") == 0 && isgraph (c)) + || (strcmp (str, "cntrl") == 0 && iscntrl (c))) + SET_LIST_BIT (c); + } + } + } + else if (translate) + SET_LIST_BIT (translate[c]); + else + SET_LIST_BIT (c); + } + + /* Discard any character set/class 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_CONTEXTUAL_INVALID_OPS) + && (! laststart || p == pend)) + goto invalid_pattern; + else if (! (obscure_syntax & RE_NO_BK_VBAR)) + goto normal_char; + else + goto handle_bar; + + case '{': + if (! ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + && (obscure_syntax & RE_INTERVALS))) + goto normal_char; + else + goto handle_interval; + + 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; + + /* Laststart should point to the start_memory that we are about + to push (unless the pattern has RE_NREGS or more ('s). */ + *stackp++ = b - bufp->buffer; + if (regnum < RE_NREGS) + { + BUFPUSH (start_memory); + BUFPUSH (regnum); + } + *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) + { + BUFPUSH (stop_memory); + BUFPUSH (stackp[-1]); + } + stackp -= 2; + fixup_jump = *stackp ? *stackp + bufp->buffer - 1 : 0; + laststart = *--stackp + bufp->buffer; + break; + + case '|': + if ((obscure_syntax & RE_LIMITED_OPS) + || (obscure_syntax & RE_NO_BK_VBAR)) + goto normal_backsl; + handle_bar: + if (obscure_syntax & RE_LIMITED_OPS) + goto normal_char; + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (6); + insert_jump (on_failure_jump, begalt, b + 6, b); + pending_exact = 0; + b += 3; + /* The alternative before the previous alternative has a + jump after it which gets executed if it gets matched. + Adjust that jump so it will jump to the previous + alternative's analogous jump (put in below, which in + turn will jump to the next (if any) alternative's such + jump, etc.). The last such jump jumps to the correct + final destination. */ + if (fixup_jump) + store_jump (fixup_jump, jump, b); + + /* Leave space for a jump after previous alternative---to be + filled in later. */ + fixup_jump = b; + b += 3; + + laststart = 0; + begalt = b; + break; + + case '{': + if (! (obscure_syntax & RE_INTERVALS) + /* Let \{ be a literal. */ + || ((obscure_syntax & RE_INTERVALS) + && (obscure_syntax & RE_NO_BK_CURLY_BRACES)) + /* If it's the string "\{". */ + || (p - 2 == pattern && p == pend)) + goto normal_backsl; + handle_interval: + beg_interval = p - 1; /* The {. */ + /* If there is no previous pattern, this isn't an interval. */ + if (!laststart) + { + if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else + goto normal_backsl; + } + /* It also isn't an interval if not preceded by an re + matching a single character or subexpression, or if + the current type of intervals can't handle back + references and the previous thing is a back reference. */ + if (! (*laststart == anychar + || *laststart == charset + || *laststart == charset_not + || *laststart == start_memory + || (*laststart == exactn && laststart[1] == 1) + || (! (obscure_syntax & RE_NO_BK_REFS) + && *laststart == duplicate))) + { + if (obscure_syntax & RE_NO_BK_CURLY_BRACES) + goto normal_char; + + /* Posix extended syntax is handled in previous + statement; this is for Posix basic syntax. */ + if (obscure_syntax & RE_INTERVALS) + goto invalid_pattern; + + goto normal_backsl; + } + lower_bound = -1; /* So can see if are set. */ + upper_bound = -1; + GET_UNSIGNED_NUMBER (lower_bound); + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) + upper_bound = RE_DUP_MAX; + } + if (upper_bound < 0) + upper_bound = lower_bound; + if (! (obscure_syntax & RE_NO_BK_CURLY_BRACES)) + { + if (c != '\\') + goto invalid_pattern; + PATFETCH (c); + } + if (c != '}' || lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound + || ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + && p != pend && *p == '{')) + { + if (obscure_syntax & RE_NO_BK_CURLY_BRACES) + goto unfetch_interval; + else + goto invalid_pattern; + } + + /* If upper_bound is zero, don't want to succeed at all; + jump from laststart to b + 3, which will be the end of + the buffer after this jump is inserted. */ + + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + insert_jump (jump, laststart, b + 3, b); + b += 3; + } + + /* Otherwise, after lower_bound number of succeeds, jump + to after the jump_n which will be inserted at the end + of the buffer, and insert that jump_n. */ + else + { /* Set to 5 if only one repetition is allowed and + hence no jump_n is inserted at the current end of + the buffer; then only space for the succeed_n is + needed. Otherwise, need space for both the + succeed_n and the jump_n. */ + + unsigned slots_needed = upper_bound == 1 ? 5 : 10; + + GET_BUFFER_SPACE ((int) slots_needed); + /* Initialize the succeed_n to n, even though it will + be set by its attendant set_number_at, because + re_compile_fastmap will need to know it. Jump to + what the end of buffer will be after inserting + this succeed_n and possibly appending a jump_n. */ + insert_jump_n (succeed_n, laststart, b + slots_needed, + b, lower_bound); + b += 5; /* Just increment for the succeed_n here. */ + + /* More than one repetition is allowed, so put in at + the end of the buffer a backward jump from b to the + succeed_n we put in above. By the time we've gotten + to this jump when matching, we'll have matched once + already, so jump back only upper_bound - 1 times. */ + + if (upper_bound > 1) + { + store_jump_n (b, jump_n, laststart, upper_bound - 1); + b += 5; + /* When hit this when matching, reset the + preceding jump_n's n to upper_bound - 1. */ + BUFPUSH (set_number_at); + GET_BUFFER_SPACE (2); + STORE_NUMBER_AND_INCR (b, -5); + STORE_NUMBER_AND_INCR (b, upper_bound - 1); + } + /* When hit this when matching, set the succeed_n's n. */ + GET_BUFFER_SPACE (5); + insert_op_2 (set_number_at, laststart, b, 5, lower_bound); + b += 5; + } + pending_exact = 0; + beg_interval = 0; + break; + + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + if (beg_interval) + p = beg_interval; + else + { + fprintf (stderr, + "regex: no interval beginning to which to backtrack.\n"); + exit (1); + } + + beg_interval = 0; + PATFETCH (c); /* normal_char expects char in `c'. */ + goto normal_char; + break; + +#ifdef emacs + case '=': + BUFPUSH (at_dot); + break; + + case 's': + laststart = b; + BUFPUSH (syntaxspec); + PATFETCH (c); + BUFPUSH (syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + BUFPUSH (notsyntaxspec); + PATFETCH (c); + BUFPUSH (syntax_spec_code[c]); + break; +#endif /* emacs */ + + case 'w': + laststart = b; + BUFPUSH (wordchar); + break; + + case 'W': + laststart = b; + BUFPUSH (notwordchar); + break; + + case '<': + BUFPUSH (wordbeg); + break; + + case '>': + BUFPUSH (wordend); + break; + + case 'b': + BUFPUSH (wordbound); + break; + + case 'B': + BUFPUSH (notwordbound); + break; + + case '`': + BUFPUSH (begbuf); + break; + + case '\'': + BUFPUSH (endbuf); + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (obscure_syntax & RE_NO_BK_REFS) + goto normal_char; + c1 = c - '0'; + if (c1 >= regnum) + { + if (obscure_syntax & RE_NO_EMPTY_BK_REF) + goto invalid_pattern; + else + goto normal_char; + } + /* Can't back reference to a subexpression if inside of it. */ + for (stackt = stackp - 2; stackt > stackb; stackt -= 4) + if (*stackt == c1) + goto normal_char; + laststart = b; + BUFPUSH (duplicate); + BUFPUSH (c1); + break; + + case '+': + case '?': + if (obscure_syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backsl; + break; + + 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: /* Expects the character in `c'. */ + 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 == '?')) + || ((obscure_syntax & RE_INTERVALS) + && ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + laststart = b; + BUFPUSH (exactn); + pending_exact = b; + BUFPUSH (0); + } + BUFPUSH (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 a jump of the form <OPCODE> <relative address>. + Store in the location FROM a jump operation to jump to relative + address FROM - TO. OPCODE is the opcode to store. */ + +static void +store_jump (char *from, char opcode, char *to) +{ + from[0] = opcode; + STORE_NUMBER(from + 1, to - (from + 3)); +} + + +/* Open up space before char FROM, and insert there a jump to TO. + CURRENT_END gives the end of the storage not 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 *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 3; /* ...to here. */ + + while (pfrom != from) + *--pto = *--pfrom; + store_jump (from, op, to); +} + + +/* Store a jump of the form <opcode> <relative address> <n> . + + Store in the location FROM a jump operation to jump to relative + address FROM - TO. OPCODE is the opcode to store, N is a number the + jump uses, say, to decide how many times to jump. + + If you call this function, you must zero out pending_exact. */ + +static void +store_jump_n (char *from, char opcode, char *to, unsigned n) +{ + from[0] = opcode; + STORE_NUMBER (from + 1, to - (from + 3)); + STORE_NUMBER (from + 3, n); +} + + +/* Similar to insert_jump, but handles a jump which needs an extra + number to handle minimum and maximum cases. Open up space at + location FROM, and insert there a jump to TO. CURRENT_END gives the + end of the storage 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_n (char op, char *from, char *to, char *current_end, unsigned n) +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 5; /* ...to here. */ + + while (pfrom != from) + *--pto = *--pfrom; + store_jump_n (from, op, to, n); +} + + +/* Open up space at location THERE, and insert operation OP followed by + NUM_1 and NUM_2. CURRENT_END gives the end of the storage in use, so + we know how much data to copy up. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_op_2 (char op, char *there, char *current_end, int num_1, int num_2) +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 5; /* ...to here. */ + + while (pfrom != there) + *--pto = *--pfrom; + + there[0] = op; + STORE_NUMBER (there + 1, num_1); + STORE_NUMBER (there + 3, num_2); +} + + + +/* 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, k; + unsigned char *translate = (unsigned char *) bufp->translate; + + unsigned char *stackb[NFAILURES]; + unsigned char **stackp = stackb; + + unsigned is_a_succeed_n; + + memset (fastmap, 0, (1 << BYTEWIDTH)); + bufp->fastmap_accurate = 1; + bufp->can_be_null = 0; + + while (p) + { + is_a_succeed_n = 0; + 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 unused: + case begline: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + 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 jump_n: + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + 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 + && (enum regexpcode) *p != succeed_n) + continue; + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (stackp != stackb && *stackp == p) + stackp--; + continue; + + case on_failure_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + *++stackp = p + j; + if (is_a_succeed_n) + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + continue; + + case succeed_n: + is_a_succeed_n = 1; + /* Get to the number of times to succeed. */ + p += 2; + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + goto handle_on_failure_jump; + } + continue; + + case set_number_at: + p += 4; + 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 /* not 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, and + doesn't let you say where to stop matching. */ + +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, (char *) 0, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in PBUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first 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, it searches + backwards, i.e., the starting positions tried are STARTPOS, STARTPOS + - 1, etc. STRING1 and STRING2 are of SIZE1 and SIZE2, respectively. + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire PBUFP->buffer and its contained + subexpressions. Do not consider matching one past the index MSTOP in + the virtual concatenation of STRING1 and STRING2. + + The value returned is the position in the strings 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_size = size1 + size2; + int endpos = startpos + range; + int val; + + /* Check for out-of-range starting position. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up range if it would eventually take startpos outside of the + virtual concatenation of string1 and string2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* Update the fastmap now if not correct already. */ + if (fastmap && !pbufp->fastmap_accurate) + re_compile_fastmap (pbufp); + + /* If the search isn't to be a backwards one, 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_size && pbufp->can_be_null != 1) + { + if (range > 0) /* Searching forwards. */ + { + 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]); + + while (range > lim && !fastmap[translate + ? translate[*p++] + : *p++]) + range--; + startpos += irange - range; + } + else /* Searching backwards. */ + { + register unsigned char c; + + if (string1 == 0 || 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_size + && fastmap && pbufp->can_be_null == 0) + return -1; + + val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, + regs, mstop); + if (val >= 0) + return startpos; + if (val == -2) + return -2; + +#ifdef C_ALLOCA + alloca (0); +#endif /* C_ALLOCA */ + + advance: + if (!range) + break; + else 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, (char *) 0, 0, string, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* The following are used for re_match_2, defined below: */ + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always pushed MAX_NUM_FAILURE_ITEMS each time we failed. */ + +int re_max_failures = 2000; + +/* Routine used by re_match_2. */ +static int bcmp_translate (char *, char *, int, unsigned char *); + + +/* Structure and accessing macros used in re_match_2: */ + +struct register_info +{ + unsigned is_active : 1; + unsigned matched_something : 1; +}; + +#define IS_ACTIVE(R) ((R).is_active) +#define MATCHED_SOMETHING(R) ((R).matched_something) + + +/* Macros used by re_match_2: */ + + +/* I.e., regstart, regend, and reg_info. */ + +#define NUM_REG_ITEMS 3 + +/* We push at most this many things on the stack whenever we + fail. The `+ 2' refers to PATTERN_PLACE and STRING_PLACE, which are + arguments to the PUSH_FAILURE_POINT macro. */ + +#define MAX_NUM_FAILURE_ITEMS (RE_NREGS * NUM_REG_ITEMS + 2) + + +/* We push this many things on the stack whenever we fail. */ + +#define NUM_FAILURE_ITEMS (last_used_reg * NUM_REG_ITEMS + 2) + + +/* This pushes most of the information about the current state we will want + if we ever fail back to it. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place) \ + { \ + short last_used_reg, this_reg; \ + \ + /* Find out how many registers are active or have been matched. \ + (Aside from register zero, which is only set at the end.) */ \ + for (last_used_reg = RE_NREGS - 1; last_used_reg > 0; last_used_reg--)\ + if (regstart[last_used_reg] != (unsigned char *) -1) \ + break; \ + \ + if (stacke - stackp < NUM_FAILURE_ITEMS) \ + { \ + unsigned char **stackx; \ + int len = stacke - stackb; \ + if (len > re_max_failures * MAX_NUM_FAILURE_ITEMS) \ + return -2; \ + \ + /* Roughly double the size of the stack. */ \ + stackx = (unsigned char **) alloca (2 * len \ + * sizeof (unsigned char *));\ + /* Only copy what is in use. */ \ + memcpy (stackx, stackb, len * sizeof (char *)); \ + stackp = stackx + (stackp - stackb); \ + stackb = stackx; \ + stacke = stackb + 2 * len; \ + } \ + \ + /* Now push the info for each of those registers. */ \ + for (this_reg = 1; this_reg <= last_used_reg; this_reg++) \ + { \ + *stackp++ = regstart[this_reg]; \ + *stackp++ = regend[this_reg]; \ + *stackp++ = (unsigned char *) ®_info[this_reg]; \ + } \ + \ + /* Push how many registers we saved. */ \ + *stackp++ = (unsigned char *) last_used_reg; \ + \ + *stackp++ = pattern_place; \ + *stackp++ = string_place; \ + } + + +/* This pops what PUSH_FAILURE_POINT pushes. */ + +#define POP_FAILURE_POINT() \ + { \ + int temp; \ + stackp -= 2; /* Remove failure points. */ \ + temp = (int) *--stackp; /* How many regs pushed. */ \ + temp *= NUM_REG_ITEMS; /* How much to take off the stack. */ \ + stackp -= temp; /* Remove the register info. */ \ + } + + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Is true if there is a first string and if PTR is pointing anywhere + inside it or just past the end. */ + +#define IS_IN_FIRST_STRING(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ + +#define PREFETCH \ + while (d == dend) \ + { \ + /* end of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* end of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Call this when have matched something; it sets `matched' flags for the + registers corresponding to the subexpressions of which we currently + are inside. */ +#define SET_REGS_MATCHED \ + { unsigned this_reg; \ + for (this_reg = 0; this_reg < RE_NREGS; this_reg++) \ + { \ + if (IS_ACTIVE(reg_info[this_reg])) \ + MATCHED_SOMETHING(reg_info[this_reg]) = 1; \ + else \ + MATCHED_SOMETHING(reg_info[this_reg]) = 0; \ + } \ + } + +/* Test if at very beginning or at very end of the virtual concatenation + of string1 and string2. If there is only one string, we've put it in + string2. */ + +#define AT_STRINGS_BEG (d == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END (d == end2) + +#define AT_WORD_BOUNDARY \ + (AT_STRINGS_BEG || AT_STRINGS_END || IS_A_LETTER (d - 1) != IS_A_LETTER (d)) + +/* We have two special cases to check for: + 1) if we're past the end of string1, we have to look at the first + character in string2; + 2) if we're before the beginning of string2, we have to look at the + last character in string1; we assume there is a string1, so use + this in conjunction with AT_STRINGS_BEG. */ +#define IS_A_LETTER(d) \ + (SYNTAX ((d) == end1 ? *string2 : (d) == string2 - 1 ? *(end1 - 1) : *(d))\ + == Sword) + + +/* Match the pattern described by PBUFP against the virtual + concatenation of STRING1 and STRING2, which are of SIZE1 and SIZE2, + respectively. Start the match at index POS in the virtual + concatenation of STRING1 and STRING2. In REGS, return the indices of + the virtual concatenation of STRING1 and STRING2 that matched the + entire PBUFP->buffer and its contained subexpressions. Do not + consider matching one past the index MSTOP in the virtual + concatenation of STRING1 and STRING2. + + 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, + char *string1_arg, int size1, + char *string2_arg, int size2, + int pos, + struct re_registers *regs, + int mstop) +{ + register unsigned char *p = (unsigned char *) pbufp->buffer; + + /* Pointer to beyond end of buffer. */ + register unsigned char *pend = p + pbufp->used; + + unsigned char *string1 = (unsigned char *) string1_arg; + unsigned char *string2 = (unsigned char *) string2_arg; + unsigned char *end1; /* Just past end of first string. */ + unsigned char *end2; /* Just past end of second string. */ + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + unsigned char *end_match_1, *end_match_2; + + register unsigned char *d, *dend; + register int mcnt; /* Multipurpose. */ + unsigned char *translate = (unsigned char *) pbufp->translate; + unsigned is_a_jump_n = 0; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to the + subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where to + resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is a + ``dummy''; if a failure happens and the failure point is a dummy, it + gets discarded and the next next one is tried. */ + + unsigned char *initial_stack[MAX_NUM_FAILURE_ITEMS * NFAILURES]; + unsigned char **stackb = initial_stack; + unsigned char **stackp = stackb; + unsigned char **stacke = &stackb[MAX_NUM_FAILURE_ITEMS * NFAILURES]; + + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ + + unsigned char *regstart[RE_NREGS]; + unsigned char *regend[RE_NREGS]; + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ + + struct register_info reg_info[RE_NREGS]; + + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + + unsigned best_regs_set = 0; + unsigned char *best_regstart[RE_NREGS]; + unsigned char *best_regend[RE_NREGS]; + + /* Initialize subexpression text positions to -1 to mark ones that no + \( or ( and \) or ) has been seen for. Also set all registers to + inactive and mark them as not having matched anything or ever + failed. */ + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + { + regstart[mcnt] = regend[mcnt] = (unsigned char *) -1; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + if (regs) + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + + /* Set up pointers to ends of strings. + Don't allow the second string to be empty unless both are empty. */ + if (size2 == 0) + { + 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; + } + + /* `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 (size1 != 0 && pos <= size1) + d = string1 + pos, dend = end_match_1; + else + d = string2 + pos - size1, dend = end_match_2; + + + /* This 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) + { + is_a_jump_n = 0; + /* End of pattern means we might have succeeded. */ + if (p == pend) + { + /* If not end of string, try backtracking. Otherwise done. */ + if (d != end_match_2) + { + if (stackp != stackb) + { + /* More failure points to try. */ + + unsigned in_same_string = + IS_IN_FIRST_STRING (best_regend[0]) + == MATCHING_IN_FIRST_STRING; + + /* If exceeds best match so far, save it. */ + if (! best_regs_set + || (in_same_string && d > best_regend[0]) + || (! in_same_string && ! MATCHING_IN_FIRST_STRING)) + { + best_regs_set = 1; + best_regend[0] = d; /* Never use regstart[0]. */ + + for (mcnt = 1; mcnt < RE_NREGS; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. */ + d = best_regend[0]; + + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } + + /* If caller wants register contents data back, convert it + to indices. */ + if (regs) + { + regs->start[0] = pos; + if (MATCHING_IN_FIRST_STRING) + 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 (IS_IN_FIRST_STRING (regstart[mcnt])) + regs->start[mcnt] = regstart[mcnt] - string1; + else + regs->start[mcnt] = regstart[mcnt] - string2 + size1; + + if (IS_IN_FIRST_STRING (regend[mcnt])) + regs->end[mcnt] = regend[mcnt] - string1; + else + regs->end[mcnt] = regend[mcnt] - string2 + size1; + } + } + return d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((enum regexpcode) *p++)) +#else + switch ((enum regexpcode) *p++) +#endif + { + + /* \( [or `(', as appropriate] is represented by start_memory, + \) by stop_memory. Both of those commands are followed by + a register number in the next byte. The text matched + within the \( and \) is recorded under that number. */ + case start_memory: + regstart[*p] = d; + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + p++; + break; + + case stop_memory: + regend[*p] = d; + IS_ACTIVE (reg_info[*p]) = 0; + + /* If just failed to match something this time around with a sub- + expression that's in a loop, try to force exit from the loop. */ + if ((! MATCHED_SOMETHING (reg_info[*p]) + || (enum regexpcode) p[-3] == start_memory) + && (p + 1) != pend) + { + register unsigned char *p2 = p + 1; + mcnt = 0; + switch (*p2++) + { + case jump_n: + is_a_jump_n = 1; + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p2); + if (is_a_jump_n) + p2 += 2; + break; + } + p2 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump, exit from the loop by forcing a + failure after pushing on the stack the on_failure_jump's + jump in the pattern, and d. */ + if (mcnt < 0 && (enum regexpcode) *p2++ == on_failure_jump) + { + EXTRACT_NUMBER_AND_INCR (mcnt, p2); + PUSH_FAILURE_POINT (p2 + mcnt, d); + goto fail; + } + } + p++; + break; + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + int regno = *p++; /* Get which register to match against */ + register unsigned char *d2, *dend2; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((IS_IN_FIRST_STRING (regstart[regno]) + == IS_IN_FIRST_STRING (regend[regno])) + ? regend[regno] : end_match_1); + while (1) + { + /* If necessary, advance to next segment in register + contents. */ + 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; + + /* If necessary, advance to next segment in data. */ + PREFETCH; + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate ((char*)d, (char*)d2, mcnt, translate) + : memcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + case anychar: + PREFETCH; /* Fetch a data character. */ + /* Match anything but a newline, maybe even a null. */ + if ((translate ? translate[*d] : *d) == '\n' + || ((obscure_syntax & RE_DOT_NOT_NULL) + && (translate ? translate[*d] : *d) == '\000')) + goto fail; + SET_REGS_MATCHED; + d++; + break; + + case charset: + case charset_not: + { + int not = 0; /* Nonzero for charset_not. */ + register int c; + if (*(p - 1) == (unsigned char) charset_not) + not = 1; + + PREFETCH; /* Fetch a data character. */ + + 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; + SET_REGS_MATCHED; + d++; + break; + } + + case begline: + if ((size1 != 0 && d == string1) + || (size1 == 0 && size2 != 0 && d == string2) + || (d && d[-1] == '\n') + || (size1 == 0 && size2 == 0)) + break; + else + 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: + on_failure: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + PUSH_FAILURE_POINT (p + mcnt, d); + break; + + /* The end of a smart repeat has a maybe_finalize_jump back. + Change it either to a finalize_jump or an ordinary jump. */ + case maybe_finalize_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + { + register unsigned char *p2 = p; + /* Compare what follows with the beginning of the repeat. + If we can establish that there is nothing that they would + both match, we can change to finalize_jump. */ + while (p2 + 1 != pend + && (*p2 == (unsigned char) stop_memory + || *p2 == (unsigned char) start_memory)) + p2 += 2; /* Skip over reg number. */ + 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; /* Point at relative address again. */ + if (p[-1] != (unsigned char) finalize_jump) + { + p[-1] = (unsigned char) jump; + goto nofinalize; + } + /* Note fall through. */ + + /* The end of a stupid repeat has a finalize_jump back to the + start, where another failure point will be made which will + point to after all the repetitions found so far. */ + + /* Take off failure points put on by matching on_failure_jump + because didn't fail. Also remove the register information + put on by the on_failure_jump. */ + case finalize_jump: + POP_FAILURE_POINT (); + /* Note fall through. */ + + /* Jump without taking off any failure points. */ + case jump: + nofinalize: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p += mcnt; + break; + + case dummy_failure_jump: + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at finalize_jump. We will end up at + finalize_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for finalize_jump to pop. */ + PUSH_FAILURE_POINT (0, 0); + goto nofinalize; + + + /* Have to succeed matching what follows at least n times. Then + just handle like an on_failure_jump. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + } + else if (mcnt == 0) + { + p[2] = unused; + p[3] = unused; + goto on_failure; + } + else + { + fprintf (stderr, "regex: the succeed_n's n is not set.\n"); + exit (1); + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER(p + 2, mcnt); + goto nofinalize; /* Do the jump without taking off + any failure points. */ + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + register unsigned char *p1; + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + STORE_NUMBER (p1, mcnt); + break; + } + + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case unused: + break; + + case wordbound: + if (AT_WORD_BOUNDARY) + break; + goto fail; + + case notwordbound: + if (AT_WORD_BOUNDARY) + goto fail; + break; + + case wordbeg: + /* Have to check if AT_STRINGS_BEG before looking at d - 1. */ + if (IS_A_LETTER (d) && (AT_STRINGS_BEG || !IS_A_LETTER (d - 1))) + break; + goto fail; + + case wordend: + /* Have to check if AT_STRINGS_BEG before looking at d - 1. */ + if (!AT_STRINGS_BEG && IS_A_LETTER (d - 1) + && (!IS_A_LETTER (d) || AT_STRINGS_END)) + break; + goto fail; + +#ifdef emacs + case before_dot: + if (PTR_CHAR_POS (d) >= point) + goto fail; + break; + + case at_dot: + if (PTR_CHAR_POS (d) != point) + goto fail; + break; + + case after_dot: + if (PTR_CHAR_POS (d) <= 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; + SET_REGS_MATCHED; + break; + + case notwordchar: + mcnt = (int) Sword; + goto matchnotsyntax; + + case notsyntaxspec: + mcnt = *p++; + matchnotsyntax: + PREFETCH; + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; + SET_REGS_MATCHED; + break; + +#else /* not emacs */ + + case wordchar: + PREFETCH; + if (!IS_A_LETTER (d)) + goto fail; + SET_REGS_MATCHED; + break; + + case notwordchar: + PREFETCH; + if (IS_A_LETTER (d)) + goto fail; + SET_REGS_MATCHED; + break; + +#endif /* not emacs */ + + case begbuf: + if (AT_STRINGS_BEG) + break; + goto fail; + + case endbuf: + if (AT_STRINGS_END) + break; + goto fail; + + case exactn: + /* Match the next few pattern characters exactly. + mcnt is how many characters to match. */ + mcnt = *p++; + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH; + if (translate[*d++] != *p++) goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH; + if (*d++ != *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED; + break; + } + continue; /* Successfully executed one pattern command; keep going. */ + + /* Jump here if any matching operation fails. */ + fail: + if (stackp != stackb) + /* A restart point is known. Restart there and pop it. */ + { + short last_used_reg, this_reg; + + /* If this failure point is from a dummy_failure_point, just + skip it. */ + if (!stackp[-2]) + { + POP_FAILURE_POINT (); + goto fail; + } + + d = *--stackp; + p = *--stackp; + if (d >= string1 && d <= end1) + dend = end_match_1; + /* Restore register info. */ + last_used_reg = (short) (int) *--stackp; + + /* Make the ones that weren't saved -1 or 0 again. */ + for (this_reg = RE_NREGS - 1; this_reg > last_used_reg; this_reg--) + { + regend[this_reg] = (unsigned char *) -1; + regstart[this_reg] = (unsigned char *) -1; + IS_ACTIVE (reg_info[this_reg]) = 0; + MATCHED_SOMETHING (reg_info[this_reg]) = 0; + } + + /* And restore the rest from the stack. */ + for ( ; this_reg > 0; this_reg--) + { + reg_info[this_reg] = *(struct register_info *) *--stackp; + regend[this_reg] = *--stackp; + regstart[this_reg] = *--stackp; + } + } + else + break; /* Matching at this starting point really fails. */ + } + + if (best_regs_set) + goto restore_best_regs; + return -1; /* Failure to match. */ +} + + +static int +bcmp_translate (char *s1, char *s2, int len, unsigned char *translate) +{ + register unsigned char *p1 = (unsigned char*)s1; + register unsigned char *p2 = (unsigned char*)s2; + while (len) + { + if (translate [*p1++] != translate [*p2++]) return 1; + len--; + } + return 0; +} + + + +/* Entry points compatible with 4.2 BSD regex library. */ + +#if 0 + +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 *) malloc (200))) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + if (!(re_comp_buf.fastmap = (char *) malloc (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, + (struct re_registers *) 0); +} +#endif /* not emacs */ + + + +#ifdef test + +#include <stdio.h> + +/* Indexed by a character, gives the upper case equivalent of the + character. */ + +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 + }; + +#ifdef canned + +#include "tests.h" + +typedef enum { extended_test, basic_test } test_type; + +/* Use this to run the tests we've thought of. */ + +void +main () +{ + test_type t = extended_test; + + if (t == basic_test) + { + printf ("Running basic tests:\n\n"); + test_posix_basic (); + } + else if (t == extended_test) + { + printf ("Running extended tests:\n\n"); + test_posix_extended (); + } +} + +#else /* not canned */ + +/* Use this to run interactive tests. */ + +void +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 *) malloc (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); + } +} + +#endif + + +#ifdef NOTDEF +void +print_buf (struct re_pattern_buffer *bufpbufp) +{ + 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 /* NOTDEF */ + +void +printchar (char c) +{ + if (c < 040 || c >= 0177) + { + putchar ('\\'); + putchar (((c >> 6) & 3) + '0'); + putchar (((c >> 3) & 7) + '0'); + putchar ((c & 7) + '0'); + } + else + putchar (c); +} + +void +error (char *string) +{ + puts (string); + exit (1); +} +#endif /* test */ diff --git a/gnu/lib/libg++/g++-include/regex.h b/gnu/lib/libg++/g++-include/regex.h new file mode 100644 index 00000000000..5561ce7aba7 --- /dev/null +++ b/gnu/lib/libg++/g++-include/regex.h @@ -0,0 +1,274 @@ +/* Definitions for data structures callers pass the regex library. + + Copyright (C) 1985, 1989-92 Free Software Foundation, Inc. + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: regex.h,v 1.1 1995/10/18 08:38:19 deraadt Exp $ +*/ + +#ifndef __REGEXP_LIBRARY +#define __REGEXP_LIBRARY + +#if defined(SHORT_NAMES) || defined(VMS) +#define re_compile_pattern recmppat +#define re_pattern_buffer repatbuf +#define re_registers reregs +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* 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 + +#define BYTEWIDTH 8 + + +/* Maximum number of duplicates an interval can allow. */ +#ifndef RE_DUP_MAX /* kludge for AIX, which defines it */ +#define RE_DUP_MAX ((1 << 15) - 1) +#endif + +/* This defines the various regexp syntaxes. */ +extern int obscure_syntax; + + +/* The following bits are used in the obscure_syntax variable to choose among + alternative regexp syntaxes. */ + +/* If this bit is set, plain parentheses serve as grouping, and backslash + parentheses are needed for literal searching. + If not set, backslash-parentheses are grouping, and plain parentheses + are for literal searching. */ +#define RE_NO_BK_PARENS 1 + +/* If this bit is set, plain | serves as the `or'-operator, and \| is a + literal. + If not set, \| serves as the `or'-operator, and | is a literal. */ +#define RE_NO_BK_VBAR (1 << 1) + +/* If this bit is not set, plain + or ? serves as an operator, and \+, \? are + literals. + If set, \+, \? are operators and plain +, ? are literals. */ +#define RE_BK_PLUS_QM (1 << 2) + +/* If this bit is set, | binds tighter than ^ or $. + If not set, the contrary. */ +#define RE_TIGHT_VBAR (1 << 3) + +/* If this bit is set, then treat newline as an OR operator. + If not set, treat it as a normal character. */ +#define RE_NEWLINE_OR (1 << 4) + +/* If this bit is set, then 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 |. + If this bit is not set, special characters (such as *, ^, and $) + always have their special meaning regardless of the surrounding + context. */ +#define RE_CONTEXT_INDEP_OPS (1 << 5) + +/* If this bit is not set, then \ before anything inside [ and ] is taken as + a real \. + If set, then such a \ escapes the following character. This is a + special case for awk. */ +#define RE_AWK_CLASS_HACK (1 << 6) + +/* If this bit is set, then \{ and \} or { and } serve as interval operators. + If not set, then \{ and \} and { and } are treated as literals. */ +#define RE_INTERVALS (1 << 7) + +/* If this bit is not set, then \{ and \} serve as interval operators and + { and } are literals. + If set, then { and } serve as interval operators and \{ and \} are + literals. */ +#define RE_NO_BK_CURLY_BRACES (1 << 8) + +/* If this bit is set, then character classes are supported; they are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (1 << 9) + +/* If this bit is set, then the dot re doesn't match a null byte. + If not set, it does. */ +#define RE_DOT_NOT_NULL (1 << 10) + +/* If this bit is set, then [^...] doesn't match a newline. + If not set, it does. */ +#define RE_HAT_NOT_NEWLINE (1 << 11) + +/* If this bit is set, back references are recognized. + If not set, they aren't. */ +#define RE_NO_BK_REFS (1 << 12) + +/* If this bit is set, back references must refer to a preceding + subexpression. If not set, a back reference to a nonexistent + subexpression is treated as literal characters. */ +#define RE_NO_EMPTY_BK_REF (1 << 13) + +/* If this bit is set, bracket expressions can't be empty. + If it is set, they can be empty. */ +#define RE_NO_EMPTY_BRACKETS (1 << 14) + +/* If this bit is set, then *, +, ? and { cannot be first in an re or + immediately after a |, or a (. Furthermore, a | cannot be first or + last in an re, or immediately follow another | or a (. Also, a ^ + cannot appear in a nonleading position and a $ cannot appear in a + nontrailing position (outside of bracket expressions, that is). */ +#define RE_CONTEXTUAL_INVALID_OPS (1 << 15) + +/* If this bit is set, then +, ? and | aren't recognized as operators. + If it's not, they are. */ +#define RE_LIMITED_OPS (1 << 16) + +/* If this bit is set, then an ending range point has to collate higher + or equal to the starting range point. + If it's not set, then when the ending range point collates higher + than the starting range point, the range is just considered empty. */ +#define RE_NO_EMPTY_RANGES (1 << 17) + +/* If this bit is set, then a hyphen (-) can't be an ending range point. + If it isn't, then it can. */ +#define RE_NO_HYPHEN_RANGE_END (1 << 18) + + +/* Define combinations of bits for the standard possibilities. */ +#define RE_SYNTAX_POSIX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS) +#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS | RE_AWK_CLASS_HACK) +#define RE_SYNTAX_EGREP (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS | RE_NEWLINE_OR) +#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) +#define RE_SYNTAX_EMACS 0 +#define RE_SYNTAX_POSIX_BASIC (RE_INTERVALS | RE_BK_PLUS_QM \ + | RE_CHAR_CLASSES | RE_DOT_NOT_NULL \ + | RE_HAT_NOT_NEWLINE | RE_NO_EMPTY_BK_REF \ + | RE_NO_EMPTY_BRACKETS | RE_LIMITED_OPS \ + | RE_NO_EMPTY_RANGES | RE_NO_HYPHEN_RANGE_END) + +#define RE_SYNTAX_POSIX_EXTENDED (RE_INTERVALS | RE_NO_BK_CURLY_BRACES \ + | RE_NO_BK_VBAR | RE_NO_BK_PARENS \ + | RE_HAT_NOT_NEWLINE | RE_CHAR_CLASSES \ + | RE_NO_EMPTY_BRACKETS | RE_CONTEXTUAL_INVALID_OPS \ + | RE_NO_BK_REFS | RE_NO_EMPTY_RANGES \ + | RE_NO_HYPHEN_RANGE_END) + + +/* This data structure is used to represent a compiled pattern. */ + +struct re_pattern_buffer + { + char *buffer; /* Space holding the compiled pattern commands. */ + long allocated; /* Size of space that `buffer' points to. */ + long 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 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. */ + }; + + +/* search.c (search_buffer) needs this one value. It is defined both in + regex.c and here. */ +#define RE_EXACTN_VALUE 1 + + +/* 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. + + For i from 1 to RE_NREGS - 1, start[i] records the starting index in + the string of where the ith subexpression matched, and end[i] records + one after the ending index. start[0] and end[0] are analogous, for + the entire pattern. */ + +struct re_registers + { + int start[RE_NREGS]; + int end[RE_NREGS]; + }; + + + +#if defined(__STDC__) || defined(__cplusplus) + +extern char *re_compile_pattern (const 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 *, char *, int, + char *, int, int, struct re_registers *, int); + +#if 0 +/* 4.2 bsd compatibility. */ +extern char *re_comp (char *); +extern int re_exec (char *); +#endif + +#else /* !__STDC__ */ + +#define const /* nothing */ +extern char *re_compile_pattern (); +/* Is this really advertised? */ +extern void re_compile_fastmap (); +extern int re_search (), re_search_2 (); +extern int re_match (), re_match_2 (); + +#if 0 +/* 4.2 bsd compatibility. */ +extern char *re_comp (); +extern int re_exec (); +#endif + +#endif /* __STDC__ */ + + +#ifdef SYNTAX_TABLE +extern char *re_syntax_table; +#endif + +#ifdef __cplusplus +extern int re_max_failures; +} +#endif + +#endif /* !__REGEXP_LIBRARY */ diff --git a/gnu/lib/libg++/g++-include/shlib_version b/gnu/lib/libg++/g++-include/shlib_version new file mode 100644 index 00000000000..b52599a164f --- /dev/null +++ b/gnu/lib/libg++/g++-include/shlib_version @@ -0,0 +1,2 @@ +major=2 +minor=0 diff --git a/gnu/lib/libg++/g++-include/sqrt.cc b/gnu/lib/libg++/g++-include/sqrt.cc new file mode 100644 index 00000000000..6df9af3790f --- /dev/null +++ b/gnu/lib/libg++/g++-include/sqrt.cc @@ -0,0 +1,43 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <math.h> + +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; + } + } +} diff --git a/gnu/lib/libg++/g++-include/std.h b/gnu/lib/libg++/g++-include/std.h new file mode 100644 index 00000000000..8d851069fda --- /dev/null +++ b/gnu/lib/libg++/g++-include/std.h @@ -0,0 +1,39 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: std.h,v 1.1 1995/10/18 08:38:20 deraadt Exp $ +*/ + + +#ifndef _std_h +#define _std_h 1 + +#include <_G_config.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> + +extern "C" { +int strcasecmp _G_ARGS((const char*, const char*)); +} + +#endif diff --git a/gnu/lib/libg++/g++-include/str.cc b/gnu/lib/libg++/g++-include/str.cc new file mode 100644 index 00000000000..bf77c02547a --- /dev/null +++ b/gnu/lib/libg++/g++-include/str.cc @@ -0,0 +1,38 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> +#include <AllocRing.h> + +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; +} diff --git a/gnu/lib/libg++/g++-include/timer.cc b/gnu/lib/libg++/g++-include/timer.cc new file mode 100644 index 00000000000..fdf35f4c18e --- /dev/null +++ b/gnu/lib/libg++/g++-include/timer.cc @@ -0,0 +1,130 @@ +/* +Copyright (C) 1990, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> + +// 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 + +#include <_G_config.h> +#include <osfcn.h> +#if !_G_HAVE_SYS_RESOURCE || !defined(RUSAGE_SELF) +#define USE_TIMES +#include <sys/param.h> +#include <sys/times.h> +#if !defined (HZ) && defined(CLK_TCK) +#define HZ CLK_TCK +#endif +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 USE_TIMES + 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 USE_TIMES + times(&New_Time); +#else + getrusage(RUSAGE_SELF,&New_Time); +#endif + if (Last_Time == 0.0) { +#ifdef USE_TIMES + 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 USE_TIMES + 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 + } + } +} + +#ifdef VMS +void sys$gettim(unsigned int*) asm("sys$gettim"); + +getrusage(int dummy,struct rusage* time){ + double rtime; + unsigned int systime[2]; + int i; + sys$gettim(&systime[0]); + rtime=systime[1]; + for(i=0;i<4;i++) rtime *= 256; + rtime+= systime[0]; +/* we subtract an offset to make sure that the number fits in a long int*/ + rtime=rtime/1.0e+7-4.144e+9; + time->ru_utime.tv_sec= rtime; + rtime=(rtime-time->ru_utime.tv_sec)*1.0e6; + time->ru_utime.tv_usec= rtime; +} +#endif +#else /* dummy them out */ + +double start_timer() +{ + return TIMER_ERROR_VALUE; +} + +double return_elapsed_time(double) +{ + return TIMER_ERROR_VALUE; +} + +#endif /* timing stuff */ + + diff --git a/gnu/lib/libg++/g++-include/values.h b/gnu/lib/libg++/g++-include/values.h new file mode 100644 index 00000000000..ba4db1ffe43 --- /dev/null +++ b/gnu/lib/libg++/g++-include/values.h @@ -0,0 +1,175 @@ +// 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 the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: values.h,v 1.1 1995/10/18 08:38:05 deraadt Exp $ +*/ + +#ifndef _values_h +#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) + +#define HIBITS MINSHORT +#define HIBITL MINLONG + +#if defined(sun) || defined(hp300) || defined(hpux) || defined(masscomp) || defined(sgi) +#ifdef masscomp +#define MAXDOUBLE \ +({ \ + double maxdouble_val; \ + \ + __asm ("fmove%.d #0x7fefffffffffffff,%0" /* Max double */ \ + : "=f" (maxdouble_val) \ + : /* no inputs */); \ + maxdouble_val; \ +}) +#define MAXFLOAT ((float) 3.40e+38) +#else +#define MAXDOUBLE 1.79769313486231470e+308 +#define MAXFLOAT ((float)3.40282346638528860e+38) +#endif +#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 <andrew%frip.wv.tek.com@relay.cs.net> */ +#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 + diff --git a/gnu/lib/libg++/genclass/Makefile b/gnu/lib/libg++/genclass/Makefile new file mode 100644 index 00000000000..68d8e6482a3 --- /dev/null +++ b/gnu/lib/libg++/genclass/Makefile @@ -0,0 +1,13 @@ +# Makefile for g++ library genclass + +PROG= genclass +SRCS= genclass.sh +NOMAN= +STRIP= + +genclass: genclass.sh + sed -e 's|^PROTODIR=.*|PROTODIR=${DESTDIR}/usr/include/g++/gen|' \ + -e 's|<VERSION>|2.4|' ${.ALLSRC} > ${.TARGET} + +.include <bsd.prog.mk> +.include "../../../usr.bin/Makefile.inc" diff --git a/gnu/lib/libg++/genclass/genclass.sh b/gnu/lib/libg++/genclass/genclass.sh new file mode 100644 index 00000000000..08d510754ad --- /dev/null +++ b/gnu/lib/libg++/genclass/genclass.sh @@ -0,0 +1,452 @@ +#!/bin/sh + +# Copyright (C) 1989 Free Software Foundation, Inc. +# +# genclass program enhanced by Wendell C. Baker +# (original 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. + + +# +# genclass -list [proto ...] +# genclass -catalog [proto ...] +# genclass type1 {ref|val} proto [out_prefix] +# genclass -2 type1 {ref|val} type2 {ref, val} proto [out_prefix] +# +# Generate classes from prototypes +# +name=genclass ; +usage=" + $name -list [proto ...] + $name -catalog [proto ...] + $name type1 {ref|val} proto [out_prefix] + $name -2 type1 {ref|val} type2 {ref|val} proto [out_prefix]" ; + +case "$1" in +-usage) + # + # -usage + # + echo "usage: $usage" 1>&2 ; + exit 0; + ;; +-version) + # + # -version + # + # <VERSION> is substituted by the build process. + # We currently use the libg++ version number (extracted from ../Makefile). + echo "$name: version <VERSION>" ; + exit 0; + ;; +-requires) + # + # -requires + # + # The following line should contain any nonstandard programs + # which must be in the users's path (i.e. not referenced by a + # fullpath);it allows one to check a script for dependencies + # without exhaustively testing its usages. + # ... in this case genclass depends on nothing else. + echo ; + exit 0; + ;; +esac ; + +# pull it in from the environment +[ "$TRACE" = "" ] || set -xv + +# Search in standard g++ prototype directory and in the current directory +# NOTE: this variable is edited by the install process +PROTODIR=/projects/gnu-cygnus/gnu-cygnus-2/mips/lib/g++-include/gen + +pwd=`pwd` + +case "$1" in +-catalog*|-list*) + # + # genclass -catalog [proto ...] + # genclass -list [proto ...] + # + option="$1" ; + shift ; + + case $# in + 0) + # + # -catalog + # -list + # + select=all ; + select_pattern=p ; + ;; + *) + # + # -catalog proto ... + # -list proto ... + # + select="$@" ; + select_pattern= ; + for i in $@ ; do + select_pattern="\ +$select_pattern +/.*$i\$/ p +" ; + done ; + + ;; + esac ; + + # + # select_pattern is now a (possibly-vacuous) newline- + # separated list of patterns of the form: + # + # /.*Proto1$/ p + # /.*Proto2$/ p + # /.*Proto3$/ p + # + # or select_pattern is simply ``p'' to select everything + + # Hmmm... not all systems have a fmt program; should we + # just go ahead and use ``nroff -Tcrt | cat -s'' here? + fmt='nroff -Tcrt | cat -s' + #fmt=fmt ; + + case "$option" in + -catalog*) + # + # -catalog [proto ...] + # + echo "\ +Catalog of ${name} class templates +directories searched: + $PROTODIR + $pwd +selecting: $select +classes available:" ; + ;; + -list*) + # + # -list [proto ...] + # + # no need to do anything (the list is coming out next) + ;; + esac ; + +# The sed script does the following: +# - If it does not end in a .ccP or .hP then +# it's not a template and we are not intereseted. +# - Get rid of pathname components [s;.*/;;] +# - Just take the template names +# - change quoting conventions and select off what we want to see +# -if it did not pass the patterns, kill it + + ls $pwd $PROTODIR | sed -e ' +/\.ccP$/ !{ + /\.hP$/ !{ + d + } +} +s;.*/;; +s/\.ccP$// +s/\.hP$// +' -e "$select_pattern +d +" | sort -u | case "$option" in + -catalog*) + # The library catalog information preceded the list + # format the list, and tab in in a bit to make it readable. + # Re-evaluate $fmt because it might contain a shell command + eval $fmt | sed -e 's/.*/ &/' ; + ;; + -list*) + # nothing special, just let the sorted list dribble out + # we must use cat to receive (and reproduce) the incoming list + cat ; + ;; + esac ; + exit 0; + ;; +-2) + # + # genclass -2 type1 {ref|val} type2 {ref|val} proto [out_prefix] + # + N=2 ; + + case $# in + 6) # genclass -2 type1 {ref|val} type2 {ref|val} proto + ;; + 7) # genclass -2 type1 {ref|val} type2 {ref|val} proto out_prefix + ;; + *) + echo "usage: $usage" 1>&2 ; + exit 1; + esac ; + shift ; + ;; +*) + # + # genclass type1 {ref|val} proto [out_prefix] + # + N=1 ; + + case $# in + 3) # genclass type1 {ref|val} proto + ;; + 4) # genclass type1 {ref|val} proto out_prefix + ;; + *) + echo "usage: $usage" 1>&2 ; + exit 1; + esac ; + ;; +esac + +# +# Args are now (the point being the leading ``-2'' is gone) +# +# type1 {ref|val} proto [out_prefix] +# type1 {ref|val} type2 {ref|val} proto [out_prefix] +# + +# +# Quote all of the $1 $2 etc references to guard against +# dynamic syntax errors due to vacuous arguments (i.e. '') +# as sometimes occurs when genclass is used from a Makefile +# + +T1="$1"; +T1NAME="$T1." ; +T1SEDNAME="$T1" ; + +case "$2" in +ref) + T1ACC="\&" ; + ;; +val) + T1ACC=" " ; + ;; +*) + echo "${name}: Must specify type1 access as ref or val" 1>&2 ; + echo "usage: $usage" 1>&2 ; + exit 1; + ;; +esac + +# N is either 1 or 2 + +case $N in +1) + # + # type1 {ref|val} proto [out_prefix] + # + class="$3" ; + + T2="" ; + T2ACC="" ; + ;; +2) + # + # type1 {ref|val} type2 {ref|val} proto [out_prefix] + # + class="$5" ; + + T2="$3"; + T2NAME="$T2." ; + T2SEDNAME="$T2" ; + + case "$4" in + ref) + T2ACC="\&" ; + ;; + val) + T2ACC=" " ; + ;; + *) + echo "${name}: Must specify type2 access: ref or val" 1>&2 ; + echo "usage: $usage" 1>&2 ; + exit 1;; + esac; + ;; +esac + +defaultprefix="$T1NAME$T2NAME" ; + +case $# in +3) # type1 {ref|val} proto + replaceprefix="N" ; + prefix="$defaultprefix" ; + ;; +5) # type1 {ref|val} type2 {ref|val} proto + replaceprefix="N" ; + prefix="$defaultprefix" ; + ;; +4) # type1 {ref|val} proto out_prefix + prefix="$4" ; + replaceprefix="Y" ; + ;; +6) # type1 {ref|val} type2 {ref|val} proto out_prefix + prefix="$6" ; + replaceprefix="Y" ; + ;; +*) + echo "${name}: too many arguments" 1>&2 ; + echo "usage: $usage" 1>&2 ; + exit 1; + ;; +esac ; + +src_h=$class.hP +src_cc=$class.ccP +out_h=$prefix$class.h; +out_cc=$prefix$class.cc ; + +# +# Note #1: The .h and .cc parts are done separately +# in case only a .h exists for the prototype +# +# Note #2: Bind the .h and .cc parts to the fullpath +# directories at the same time to ensure consistency. +# + +if [ -f $pwd/$src_h ] ; then + fullsrc_h=$pwd/$src_h ; + fullsrc_cc=$pwd/$src_cc ; +elif [ -f $PROTODIR/$src_h ] ; then + fullsrc_h=$PROTODIR/$src_h ; + fullsrc_cc=$PROTODIR/$src_cc ; +else + echo "${name}: there is no prototype for class $class - file $src_h" 1>&2 ; + $0 -list ; + exit 1; +fi + +CASES="$N$replaceprefix" ; +# CASES is one of { 2Y 2N 1Y 1N } + +# +# WATCHOUT - we have no way of checking whether or not +# the proper case type is being used with the prototype. +# +# For example, we have no way of ensuring that any of +# Map variants are specified with the -2 argument set +# Further, we have no way of ensuring that -2 is not +# used with the prototypes which require only one. +# +# The second problem is not serious because it still +# results in correctly-generated C++ code; the first +# problem is serious because it results in C++ code that +# still has ``<C>'' and ``<C&>'' syntax inside it. Such +# code of course will not compile. +# +# SO THE BEST WE CAN DO - is check for the presence of +# <C> and <C&> AFTER the thing has been generated. +# + +case $CASES in +2Y) # Two output substitutions, change the prefix + sed < $fullsrc_h > $out_h -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/<C>/$T2/g +s/<C&>/$T2$T2ACC/g +s/$T1SEDNAME\.$T2SEDNAME\./$prefix/g +s/$T1SEDNAME\./$prefix/g +s/$T2SEDNAME\./$prefix/g +" ; + ;; +2N) # Two output substitutions, use the default prefix + sed < $fullsrc_h > $out_h -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/<C>/$T2/g +s/<C&>/$T2$T2ACC/g +" ; + ;; +1Y) # One output substitution, change the prefix + sed < $fullsrc_h > $out_h -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/$T1SEDNAME\./$prefix/g +" ; + ;; +1N) # One output substitution, use the default prefix + sed < $fullsrc_h > $out_h -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +" ; + ;; +esac + +if egrep '<C&?>' $out_h > /dev/null ; then + echo "${name}: the $class class requires the -2 syntax for the 2nd type" 1>&2 ; + echo "usage: $usage" 1>&2 ; + # the user does not get to see the mistakes (he might try to compile it) + rm $out_h ; + exit 1; +fi ; + +if [ ! -f $fullsrc_cc ] ; then + echo "${name}: warning, class has a .h but no .cc file" 1>&2 ; + exit 0; +fi + +case $CASES in +2Y) # Two output substitutions, change the prefix + sed < $fullsrc_cc > $out_cc -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/<C>/$T2/g +s/<C&>/$T2$T2ACC/g +s/$T1SEDNAME\.$T2SEDNAME\./$prefix/g +s/$T1SEDNAME\./$prefix/g +s/$T2SEDNAME\./$prefix/g +" + ;; +2N) # Two output substitutions, use the default prefix + sed < $fullsrc_cc > $out_cc -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/<C>/$T2/g +s/<C&>/$T2$T2ACC/g +" + ;; +1Y) # One output substitution, change the prefix + sed < $fullsrc_cc > $out_cc -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +s/$T1SEDNAME\./$prefix/g +" + ;; +1N) # One output substitution, use the default prefix + sed < $fullsrc_cc > $out_cc -e " +s/<T>/$T1/g +s/<T&>/$T1$T1ACC/g +" + ;; +esac + +if egrep '<C&?>' $out_h $out_cc > /dev/null ; then + echo "${name}: the $class class requires the -2 syntax for the 2nd type" 1>&2 ; + echo "usage: $usage" 1>&2 ; + # the user does not get to see the mistakes (he might try to compile it) + rm $out_h $out_cc ; + exit 1; +fi ; + +exit 0; diff --git a/gnu/lib/libg++/iostream/PlotFile.C b/gnu/lib/libg++/iostream/PlotFile.C new file mode 100644 index 00000000000..306ba5e9026 --- /dev/null +++ b/gnu/lib/libg++/iostream/PlotFile.C @@ -0,0 +1,130 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + converted to use iostream library by Per Bothner (bothner@cygnus.com) + +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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <PlotFile.h> + +/* + PlotFile implementation module +*/ + + +PlotFile& PlotFile:: cmd(char c) +{ + ofstream::put(c); + return *this; +} + +PlotFile& PlotFile:: operator<<(const int x) +{ +#if defined(convex) + ofstream::put((char)(x>>8)); + ofstream::put((char)(x&0377)); +#else + ofstream::put((char)(x&0377)); + ofstream::put((char)(x>>8)); +#endif + return *this; +} + +PlotFile& PlotFile:: operator<<(const char *s) +{ + *(ofstream*)this << 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; +} diff --git a/gnu/lib/libg++/iostream/PlotFile.h b/gnu/lib/libg++/iostream/PlotFile.h new file mode 100644 index 00000000000..5a85a5cd2cc --- /dev/null +++ b/gnu/lib/libg++/iostream/PlotFile.h @@ -0,0 +1,120 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + converted to use iostream library by Per Bothner (bothner@cygnus.com) + +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. + + $Id: PlotFile.h,v 1.1 1995/10/18 08:38:11 deraadt Exp $ +*/ + +/* + 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 +#ifdef __GNUG__ +#pragma interface +#endif +#define _PlotFile_h + +#include <fstream.h> + +/* + 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 : public ofstream +{ +protected: + PlotFile& cmd(char c); + PlotFile& operator << (const int x); + PlotFile& operator << (const char *s); + +public: + + PlotFile() : ofstream() { } + PlotFile(int fd) : ofstream(fd) { } + PlotFile(const char *name, int mode=ios::out, int prot=0664) + : ofstream(name, mode, prot) { } + +// PlotFile& remove() { ofstream::remove(); return *this; } + +// int filedesc() { return ofstream::filedesc(); } +// const char* name() { return File::name(); } +// void setname(const char* newname) { File::setname(newname); } +// int iocount() { return File::iocount(); } + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gnu/lib/libg++/iostream/SFile.C b/gnu/lib/libg++/iostream/SFile.C new file mode 100644 index 00000000000..9221bb34f7b --- /dev/null +++ b/gnu/lib/libg++/iostream/SFile.C @@ -0,0 +1,58 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <SFile.h> + +SFile::SFile(const char *filename, int size, int mode, int prot) +: fstream(filename, mode, prot) +{ + sz = size; +} + +SFile::SFile(int fd, int size) +: fstream(fd) +{ + sz = size; +} + +void SFile::open(const char *name, int size, int mode, int prot) +{ + fstream::open(name, mode, prot); + sz = size; +} + +SFile& SFile::get(void* x) +{ + read(x, sz); + return *this; +} + +SFile& SFile::put(void* x) +{ + write(x, sz); + return *this; +} + +SFile& SFile::operator[](long i) +{ + if (rdbuf()->seekoff(i * sz, ios::beg) == EOF) + set(ios::badbit); + return *this; +} diff --git a/gnu/lib/libg++/iostream/SFile.h b/gnu/lib/libg++/iostream/SFile.h new file mode 100644 index 00000000000..d7b75225272 --- /dev/null +++ b/gnu/lib/libg++/iostream/SFile.h @@ -0,0 +1,48 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. This library is free +software; you can redistribute it and/or modify it under the terms of +the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. This library 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 Library General Public License for more details. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: SFile.h,v 1.1 1995/10/18 08:38:12 deraadt Exp $ +*/ + +#ifndef _SFile_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _SFile_h 1 + +#include <fstream.h> + +class SFile: public fstream +{ + protected: + int sz; // unit size for structured binary IO + +public: + SFile() : fstream() { } + SFile(int fd, int size); + SFile(const char *name, int size, int mode, int prot=0664); + void open(const char *name, int size, int mode, int prot=0664); + + int size() { return sz; } + int setsize(int s) { int old = sz; sz = s; return old; } + + SFile& get(void* x); + SFile& put(void* x); + SFile& operator[](long i); +}; + +#endif diff --git a/gnu/lib/libg++/iostream/editbuf.C b/gnu/lib/libg++/iostream/editbuf.C new file mode 100644 index 00000000000..3d99e8442d1 --- /dev/null +++ b/gnu/lib/libg++/iostream/editbuf.C @@ -0,0 +1,707 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "ioprivate.h" +#include "editbuf.h" +#include <stddef.h> + +/* NOTE: Some of the code here is taken from GNU emacs */ +/* Hence this file falls under the GNU License! */ + +// Invariants for edit_streambuf: +// An edit_streambuf is associated with a specific edit_string, +// which again is a sub-string of a specific edit_buffer. +// An edit_streambuf is always in either get mode or put mode, never both. +// In get mode, gptr() is the current position, +// and pbase(), pptr(), and epptr() are all NULL. +// In put mode, pptr() is the current position, +// and eback(), gptr(), and egptr() are all NULL. +// Any edit_streambuf that is actively doing insertion (as opposed to +// replacing) // must have its pptr() pointing to the start of the gap. +// Only one edit_streambuf can be actively inserting into a specific +// edit_buffer; the edit_buffer's _writer field points to that edit_streambuf. +// That edit_streambuf "owns" the gap, and the actual start of the +// gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer +// will only be updated on an edit_streambuf::overflow(). + +int edit_streambuf::truncate() +{ + str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()), + str->buffer->tell(str->end)); + return 0; +} + +#ifdef OLD_STDIO +inline void disconnect_gap_from_file(edit_buffer* buffer, FILE* fp) +{ + if (buffer->gap_start_ptr != &fp->__bufp) + return; + buffer->gap_start_normal = fp->__bufp; + buffer->gap_start_ptr = &buffer->gap_start_normal; +} +#endif + +void edit_streambuf::flush_to_buffer(edit_buffer* buffer) +{ + if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end()) + buffer->_gap_start = pptr(); +} + +void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer) +{ + if (buffer->_writer != this) return; + flush_to_buffer(buffer); + setp(pptr(),pptr()); + buffer->_writer = NULL; +} + +buf_index edit_buffer::tell(buf_char *ptr) +{ + if (ptr <= gap_start()) + return ptr - data; + else + return ptr - gap_end() + size1(); +} + +#if 0 +buf_index buf_cookie::tell() +{ + return str->buffer->tell(file->__bufp); +} +#endif + +buf_index edit_buffer::tell(edit_mark*mark) +{ + return tell(data + mark->index_in_buffer(this)); +} + +// adjust the position of the gap + +void edit_buffer::move_gap(buf_offset pos) +{ + if (pos < size1()) + gap_left (pos); + else if (pos > size1()) + gap_right (pos); +} + +void edit_buffer::gap_left (int pos) +{ + register buf_char *to, *from; + register int i; + int new_s1; + + i = size1(); + from = gap_start(); + to = from + gap_size(); + new_s1 = size1(); + + /* Now copy the characters. To move the gap down, + copy characters up. */ + + for (;;) + { + /* I gets number of characters left to copy. */ + i = new_s1 - pos; + if (i == 0) + break; +#if 0 + /* If a quit is requested, stop copying now. + Change POS to be where we have actually moved the gap to. */ + if (QUITP) + { + pos = new_s1; + break; + } +#endif + /* Move at most 32000 chars before checking again for a quit. */ + if (i > 32000) + i = 32000; + new_s1 -= i; + while (--i >= 0) + *--to = *--from; + } + + /* Adjust markers, and buffer data structure, to put the gap at POS. + POS is where the loop above stopped, which may be what was specified + or may be where a quit was detected. */ + adjust_markers (pos << 1, size1() << 1, gap_size(), data); +#ifndef OLD_STDIO + _gap_start = data + pos; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + pos; +#endif + __gap_end_pos = to - data; +/* QUIT;*/ +} + +void edit_buffer::gap_right (int pos) +{ + register buf_char *to, *from; + register int i; + int new_s1; + + i = size1(); + to = gap_start(); + from = i + gap_end(); + new_s1 = i; + + /* Now copy the characters. To move the gap up, + copy characters down. */ + + while (1) + { + /* I gets number of characters left to copy. */ + i = pos - new_s1; + if (i == 0) + break; +#if 0 + /* If a quit is requested, stop copying now. + Change POS to be where we have actually moved the gap to. */ + if (QUITP) + { + pos = new_s1; + break; + } +#endif + /* Move at most 32000 chars before checking again for a quit. */ + if (i > 32000) + i = 32000; + new_s1 += i; + while (--i >= 0) + *to++ = *from++; + } + + adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1, + - gap_size(), data); +#ifndef OLD_STDIO + _gap_start = data+pos; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + pos; +#endif + __gap_end_pos = from - data; +/* QUIT;*/ +} + +/* make sure that the gap in the current buffer is at least k + characters wide */ + +void edit_buffer::make_gap(buf_offset k) +{ + register buf_char *p1, *p2, *lim; + buf_char *old_data = data; + int s1 = size1(); + + if (gap_size() >= k) + return; + + /* Get more than just enough */ + if (buf_size > 1000) k += 2000; + else k += /*200;*/ 20; // for testing! + + p1 = (buf_char *) realloc (data, s1 + size2() + k); + if (p1 == 0) + abort(); /*memory_full ();*/ + + k -= gap_size(); /* Amount of increase. */ + + /* Record new location of text */ + data = p1; + + /* Transfer the new free space from the end to the gap + by shifting the second segment upward */ + p2 = data + buf_size; + p1 = p2 + k; + lim = p2 - size2(); + while (lim < p2) + *--p1 = *--p2; + + /* Finish updating text location data */ + __gap_end_pos += k; + +#ifndef OLD_STDIO + _gap_start = data + s1; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + s1; +#endif + + /* adjust markers */ + adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data); + buf_size += k; +} + +/* Add `amount' to the position of every marker in the current buffer + whose current position is between `from' (exclusive) and `to' (inclusive). + Also, any markers past the outside of that interval, in the direction + of adjustment, are first moved back to the near end of the interval + and then adjusted by `amount'. */ + +void edit_buffer::adjust_markers(register mark_pointer low, + register mark_pointer high, + int amount, buf_char *old_data) +{ + register struct edit_mark *m; + register mark_pointer mpos; + /* convert to mark_pointer */ + amount <<= 1; + + if (_writer) + _writer->disconnect_gap_from_file(this); + + for (m = mark_list(); m != NULL; m = m->chain) + { + mpos = m->_pos; + if (amount > 0) + { + if (mpos > high && mpos < high + amount) + mpos = high + amount; + } + else + { + if (mpos > low + amount && mpos <= low) + mpos = low + amount; + } + if (mpos > low && mpos <= high) + mpos += amount; + m->_pos = mpos; + } + + // Now adjust files + edit_streambuf *file; + + for (file = files; file != NULL; file = file->next) { + mpos = file->current() - old_data; + if (amount > 0) + { + if (mpos > high && mpos < high + amount) + mpos = high + amount; + } + else + { + if (mpos > low + amount && mpos <= low) + mpos = low + amount; + } + if (mpos > low && mpos <= high) + mpos += amount; + char* new_pos = data + mpos; + file->set_current(new_pos, file->is_reading()); + } +} + +#if 0 +stdio_ + __off == index at start of buffer (need only be valid after seek ? ) + __buf == + +if read/read_delete/overwrite mode: + __endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer)) + +if inserting: + must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp + file->edit_string->end->ptr(buffer) == *gap_start_ptr+end +if write_mode: + if before gap +#endif + +int edit_streambuf::underflow() +{ + if (!(_mode & ios::in)) + return EOF; + struct edit_buffer *buffer = str->buffer; + if (!is_reading()) { // Must switch from put to get mode. + disconnect_gap_from_file(buffer); + set_current(pptr(), 1); + } + buf_char *str_end = str->end->ptr(buffer); + retry: + if (gptr() < egptr()) { + return *gptr(); + } + if ((buf_char*)gptr() == str_end) + return EOF; + if (str_end <= buffer->gap_start()) { + setg(eback(), gptr(), str_end); + goto retry; + } + if (gptr() < buffer->gap_start()) { + setg(eback(), gptr(), buffer->gap_start()); + goto retry; + } + if (gptr() == buffer->gap_start()) { + disconnect_gap_from_file(buffer); +// fp->__offset += fp->__bufp - fp->__buffer; + setg(buffer->gap_end(), buffer->gap_end(), str_end); + } + else + setg(eback(), gptr(), str_end); + goto retry; +} + +int edit_streambuf::overflow(int ch) +{ + if (_mode == ios::in) + return EOF; + struct edit_buffer *buffer = str->buffer; + flush_to_buffer(buffer); + if (ch == EOF) + return 0; + if (is_reading()) { // Must switch from get to put mode. + set_current(gptr(), 0); + } + buf_char *str_end = str->end->ptr(buffer); + retry: + if (pptr() < epptr()) { + *pptr() = ch; + pbump(1); + return (unsigned char)ch; + } + if ((buf_char*)pptr() == str_end || inserting()) { + /* insert instead */ + if (buffer->_writer) + buffer->_writer->flush_to_buffer(); // Redundant? + buffer->_writer = NULL; + if (pptr() >= buffer->gap_end()) + buffer->move_gap(pptr() - buffer->gap_size()); + else + buffer->move_gap(pptr()); + buffer->make_gap(1); + setp(buffer->gap_start(), buffer->gap_end()); + buffer->_writer = this; + *pptr() = ch; + pbump(1); + return (unsigned char)ch; + } + if (str_end <= buffer->gap_start()) { + // Entire string is left of gap. + setp(pptr(), str_end); + } + else if (pptr() < buffer->gap_start()) { + // Current pos is left of gap. + setp(pptr(), buffer->gap_start()); + goto retry; + } + else if (pptr() == buffer->gap_start()) { + // Current pos is at start of gap; move to end of gap. +// disconnect_gap_from_file(buffer); + setp(buffer->gap_end(), str_end); +// __offset += __bufp - __buffer; + } + else { + // Otherwise, current pos is right of gap. + setp(pptr(), str_end); + } + goto retry; +} + +void edit_streambuf::set_current(char *new_pos, int reading) +{ + if (reading) { + setg(new_pos, new_pos, new_pos); + setp(NULL, NULL); + } + else { + setg(NULL, NULL, NULL); + setp(new_pos, new_pos); + } +} + +// Called by fseek(fp, pos, whence) if fp is bound to a edit_buffer. + +streampos edit_streambuf::seekoff(streamoff offset, _seek_dir dir, + int mode /* =ios::in|ios::out*/) +{ + struct edit_buffer *buffer = str->buffer; + disconnect_gap_from_file(buffer); + buf_index cur_pos = buffer->tell((buf_char*)current());; + buf_index start_pos = buffer->tell(str->start); + buf_index end_pos = buffer->tell(str->end); + switch (dir) { + case ios::beg: + offset += start_pos; + break; + case ios::cur: + offset += cur_pos; + break; + case ios::end: + offset += end_pos; + break; + } + if (offset < start_pos || offset > end_pos) + return EOF; + buf_char *new_pos = buffer->data + offset; + buf_char* gap_start = buffer->gap_start(); + if (new_pos > gap_start) { + buf_char* gap_end = buffer->gap_end(); + new_pos += gap_end - gap_start; + if (new_pos >= buffer->data + buffer->buf_size) abort(); // Paranoia. + } + set_current(new_pos, is_reading()); + return EOF; +} + +#if 0 +int buf_seek(void *arg_cookie, fpos_t * pos, int whence) +{ + struct buf_cookie *cookie = arg_cookie; + FILE *file = cookie->file; + struct edit_buffer *buffer = cookie->str->buffer; + buf_char *str_start = cookie->str->start->ptr(buffer); + disconnect_gap_from_file(buffer, cookie->file); + fpos_t cur_pos, new_pos; + if (file->__bufp <= *buffer->gap_start_ptr + || str_start >= buffer->__gap_end) + cur_pos = str_start - file->__bufp; + else + cur_pos = + (*buffer->gap_start_ptr - str_start) + (file->__bufp - __gap_end); + end_pos = ...; + switch (whence) { + case SEEK_SET: + new_pos = *pos; + break; + case SEEK_CUR: + new_pos = cur_pos + *pos; + break; + case SEEK_END: + new_pos = end_pos + *pos; + break; + } + if (new_pos > end_pos) { + seek to end_pos; + insert_nulls(new_pos - end_pos); + return; + } + if (str_start + new_pos <= *gap_start_ptr &* *gap_start_ptr < end) { + __buffer = str_start; + __off = 0; + __bufp = str_start + new_pos; + file->__get_limit = + *buffer->gap_start_ptr; /* what if gap_start_ptr == &bufp ??? */ + } else if () { + + } + *pos = new_pos; +} +#endif + +/* Delete characters from `from' up to (but not incl) `to' */ + +void edit_buffer::delete_range (buf_index from, buf_index to) +{ + register int numdel; + + if ((numdel = to - from) <= 0) + return; + + /* Make sure the gap is somewhere in or next to what we are deleting */ + if (from > size1()) + gap_right (from); + if (to < size1()) + gap_left (to); + + /* Relocate all markers pointing into the new, larger gap + to point at the end of the text before the gap. */ + adjust_markers ((to + gap_size()) << 1, (to + gap_size()) << 1, + - numdel - gap_size(), data); + + __gap_end_pos = to + gap_size(); + _gap_start = data + from; +} + +void edit_buffer::delete_range(struct edit_mark *start, struct edit_mark *end) +{ + delete_range(tell(start), tell(end)); +} + +void buf_delete_chars(struct edit_buffer *buf, struct edit_mark *mark, size_t count) +{ + abort(); +} + +edit_streambuf::edit_streambuf(edit_string* bstr, int mode) +{ + _mode = mode; + str = bstr; + edit_buffer* buffer = bstr->buffer; + next = buffer->files; + buffer->files = this; + char* buf_ptr = bstr->start->ptr(buffer); + _inserting = 0; +// setb(buf_ptr, buf_ptr, 0); + set_current(buf_ptr, !(mode & ios::out+ios::trunc+ios::app)); + if (_mode & ios::trunc) + truncate(); + if (_mode & ios::ate) + seekoff(0, ios::end); +} + +// Called by fclose(fp) if fp is bound to a edit_buffer. + +#if 0 +static int buf_close(void *arg) +{ + register struct buf_cookie *cookie = arg; + struct edit_buffer *buffer = cookie->str->buffer; + struct buf_cookie **ptr; + for (ptr = &buffer->files; *ptr != cookie; ptr = &(*ptr)->next) ; + *ptr = cookie->next; + disconnect_gap_from_file(buffer, cookie->file); + free (cookie); + return 0; +} +#endif + +edit_streambuf::~edit_streambuf() +{ + if (_mode == ios::out) + truncate(); + // Unlink this from list of files associated with bstr->buffer. + edit_streambuf **ptr = &str->buffer->files; + for (; *ptr != this; ptr = &(*ptr)->next) { } + *ptr = next; + + disconnect_gap_from_file(str->buffer); +} + +edit_buffer::edit_buffer() +{ + buf_size = /*200;*/ 15; /* for testing! */ + data = (buf_char*)malloc(buf_size); + files = NULL; +#ifndef OLD_STDIO + _gap_start = data; + _writer = NULL; +#else + gap_start_normal = data; + gap_start_ptr = &gap_start_normal; +#endif + __gap_end_pos = buf_size; + start_mark.chain = &end_mark; + start_mark._pos = 0; + end_mark.chain = NULL; + end_mark._pos = 2 * buf_size + 1; +} + +// Allocate a new mark, which is adjusted by 'delta' bytes from 'this'. +// Restrict new mark to lie within 'str'. + +edit_mark::edit_mark(struct edit_string *str, long delta) +{ + struct edit_buffer *buf = str->buffer; + chain = buf->start_mark.chain; + buf->start_mark.chain = this; + mark_pointer size1 = buf->size1() << 1; + int gap_size = buf->gap_size() << 1; + delta <<= 1; + + // check if new and old marks are opposite sides of gap + if (_pos <= size1 && _pos + delta > size1) + delta += gap_size; + else if (_pos >= size1 + gap_size && _pos + delta < size1 + gap_size) + delta -= gap_size; + + _pos = _pos + delta; + if (_pos < str->start->_pos & ~1) + _pos = (str->start->_pos & ~ 1) + (_pos & 1); + else if (_pos >= str->end->_pos) + _pos = (str->end->_pos & ~ 1) + (_pos & 1); +} + +// A (slow) way to find the buffer a mark belongs to. + +edit_buffer * edit_mark::buffer() +{ + struct edit_mark *mark; + for (mark = this; mark->chain != NULL; mark = mark->chain) ; + // Assume that the last mark on the chain is the end_mark. + return (edit_buffer *)((char*)mark - offsetof(edit_buffer, end_mark)); +} + +edit_mark::~edit_mark() +{ + // Must unlink mark from chain of owning buffer + struct edit_buffer *buf = buffer(); + if (this == &buf->start_mark || this == &buf->end_mark) abort(); + edit_mark **ptr; + for (ptr = &buf->start_mark.chain; *ptr != this; ptr = &(*ptr)->chain) ; + *ptr = this->chain; +} + +int edit_string::length() const +{ + ptrdiff_t delta = end->ptr(buffer) - start->ptr(buffer); + if (end->ptr(buffer) <= buffer->gap_start() || + start->ptr(buffer) >= buffer->gap_end()) + return delta; + return delta - buffer->gap_size(); +} + +buf_char * edit_string::copy_bytes(int *lenp) const +{ + char *new_str; + int len1, len2; + buf_char *start1, *start2; + start1 = start->ptr(buffer); + if (end->ptr(buffer) <= buffer->gap_start() + || start->ptr(buffer) >= buffer->gap_end()) { + len1 = end->ptr(buffer) - start1; + len2 = 0; + start2 = NULL; // To avoid a warning from g++. + } + else { + len1 = buffer->gap_start() - start1; + start2 = buffer->gap_end(); + len2 = end->ptr(buffer) - start2; + } + new_str = (char*)malloc(len1 + len2 + 1); + memcpy(new_str, start1, len1); + if (len2 > 0) memcpy(new_str + len1, start2, len2); + new_str[len1+len2] = '\0'; + *lenp = len1+len2; + return new_str; +} + +// Replace the buf_chars in 'this' with ones from 'src'. +// Equivalent to deleting this, then inserting src, except tries +// to leave marks in place: Marks whose offset from the start +// of 'this' is less than 'src->length()' will still have the +// same offset in 'this' when done. + +void edit_string::assign(struct edit_string *src) +{ + edit_streambuf dst_file(this, ios::out); + if (buffer == src->buffer /*&& ???*/) { /* overly conservative */ + int src_len; + buf_char *new_str; + new_str = src->copy_bytes(&src_len); + dst_file.sputn(new_str, src_len); + free (new_str); + } else { + edit_streambuf src_file(src, ios::in); + for ( ; ; ) { + int ch = src_file.sbumpc(); + if (ch == EOF) break; + dst_file.sputc(ch); + } + } +} diff --git a/gnu/lib/libg++/iostream/editbuf.h b/gnu/lib/libg++/iostream/editbuf.h new file mode 100644 index 00000000000..6562d73702e --- /dev/null +++ b/gnu/lib/libg++/iostream/editbuf.h @@ -0,0 +1,175 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: editbuf.h,v 1.1 1995/10/18 08:38:12 deraadt Exp $ + +#ifndef _EDITBUF_H +#define _EDITBUF_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <stdio.h> +#include <fstream.h> + +typedef unsigned long mark_pointer; +// At some point, it might be nice to parameterize this code +// in terms of buf_char. +typedef /*unsigned*/ char buf_char; + +// Logical pos from start of buffer (does not count gap). +typedef long buf_index; + +// Pos from start of buffer, possibly including gap_size. +typedef long buf_offset; + +#if 0 +struct buf_cookie { + FILE *file; + struct edit_string *str; + struct buf_cookie *next; + buf_index tell(); +}; +#endif + +struct edit_buffer; +struct edit_mark; + +// A edit_string is defined as the region between the 'start' and 'end' marks. +// Normally (always?) 'start->insert_before()' should be false, +// and 'end->insert_before()' should be true. + +struct edit_string { + struct edit_buffer *buffer; // buffer that 'start' and 'end' belong to + struct edit_mark *start, *end; + int length() const; // count of buf_chars currently in string + edit_string(struct edit_buffer *b, + struct edit_mark *ms, struct edit_mark *me) + { buffer = b; start = ms; end = me; } +/* Make a fresh, contiguous copy of the data in STR. + Assign length of STR to *LENP. + (Output has extra NUL at out[*LENP].) */ + buf_char *copy_bytes(int *lenp) const; +// FILE *open_file(char *mode); + void assign(struct edit_string *src); // copy bytes from src to this +}; + +struct edit_streambuf : public streambuf { + friend edit_buffer; + edit_string *str; + edit_streambuf* next; // Chain of edit_streambuf's for a edit_buffer. + short _mode; + edit_streambuf(edit_string* bstr, int mode); + ~edit_streambuf(); + virtual int underflow(); + virtual int overflow(int c = EOF); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + void flush_to_buffer(); + void flush_to_buffer(edit_buffer* buffer); + int _inserting; + int inserting() { return _inserting; } + void inserting(int i) { _inserting = i; } +// int delete_chars(int count, char* cut_buf); Not implemented. + int truncate(); + int is_reading() { return gptr() != NULL; } + buf_char* current() { return is_reading() ? gptr() : pptr(); } + void set_current(char *p, int is_reading); + protected: + void disconnect_gap_from_file(edit_buffer* buffer); +}; + +// A 'edit_mark' indicates a position in a buffer. +// It is "attached" the text (rather than the offset). +// There are two kinds of mark, which have different behavior +// when text is inserted at the mark: +// If 'insert_before()' is true the mark will be adjusted to be +// *after* the new text. + +struct edit_mark { + struct edit_mark *chain; + mark_pointer _pos; + inline int insert_before() { return _pos & 1; } + inline unsigned long index_in_buffer(struct edit_buffer *buffer) + { return _pos >> 1; } + inline buf_char *ptr(struct edit_buffer *buf); + buf_index tell(); + edit_mark() { } + edit_mark(struct edit_string *str, long delta); + edit_buffer *buffer(); + ~edit_mark(); +}; + +// A 'edit_buffer' consists of a sequence of buf_chars (the data), +// a list of edit_marks pointing into the data, and a list of FILEs +// also pointing into the data. +// A 'edit_buffer' coerced to a edit_string is the string of +// all the buf_chars in the buffer. + +// This implementation uses a conventional buffer gap (as in Emacs). +// The gap start is defined by de-referencing a (buf_char**). +// This is because sometimes a FILE is inserting into the buffer, +// so rather than having each putc adjust the gap, we use indirection +// to have the gap be defined as the write pointer of the FILE. +// (This assumes that putc adjusts a pointer (as in GNU's libc), not an index.) + +struct edit_buffer { + buf_char *data; /* == emacs buffer_text.p1+1 */ + buf_char *_gap_start; + edit_streambuf* _writer; // If non-NULL, currently writing stream + inline buf_char *gap_start() + { return _writer ? _writer->pptr() : _gap_start; } + buf_offset __gap_end_pos; // size of part 1 + size of gap + /* int gap; implicit: buf_size - size1 - size2 */ + int buf_size; + struct edit_streambuf *files; + struct edit_mark start_mark; + struct edit_mark end_mark; + edit_buffer(); + inline buf_offset gap_end_pos() { return __gap_end_pos; } + inline struct edit_mark *start_marker() { return &start_mark; } + inline struct edit_mark *end_marker() { return &end_mark; } +/* these should be protected, ultimately */ + buf_index tell(edit_mark*); + buf_index tell(buf_char*); + inline buf_char *gap_end() { return data + gap_end_pos(); } + inline int gap_size() { return gap_end() - gap_start(); } + inline int size1() { return gap_start() - data; } + inline int size2() { return buf_size - gap_end_pos(); } + inline struct edit_mark * mark_list() { return &start_mark; } + void make_gap (buf_offset); + void move_gap (buf_offset pos); + void move_gap (buf_char *pos) { move_gap(pos - data); } + void gap_left (int pos); + void gap_right (int pos); + void adjust_markers(mark_pointer low, mark_pointer high, + int amount, buf_char *old_data); + void delete_range(buf_index from, buf_index to); + void delete_range(struct edit_mark *start, struct edit_mark *end); +}; + +extern buf_char * bstr_copy(struct edit_string *str, int *lenp); + +// Convert a edit_mark to a (buf_char*) + +inline buf_char *edit_mark::ptr(struct edit_buffer *buf) + { return buf->data + index_in_buffer(buf); } + +inline void edit_streambuf::flush_to_buffer() +{ + edit_buffer* buffer = str->buffer; + if (buffer->_writer == this) flush_to_buffer(buffer); +} +#endif /* !_EDITBUF_H*/ + diff --git a/gnu/lib/libg++/iostream/filebuf.C b/gnu/lib/libg++/iostream/filebuf.C new file mode 100644 index 00000000000..4d49d7f0e60 --- /dev/null +++ b/gnu/lib/libg++/iostream/filebuf.C @@ -0,0 +1,580 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991, 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +// An fstream can be in at most one of put mode, get mode, or putback mode. +// Putback mode is a variant of get mode. + +// In a filebuf, there is only one current position, instead of two +// separate get and put pointers. In get mode, the current posistion +// is that of gptr(); in put mode that of pptr(). + +// The position in the buffer that corresponds to the position +// in external file system is file_ptr(). +// This is normally egptr(), except in putback mode, when it is _save_egptr. +// If the field _fb._offset is >= 0, it gives the offset in +// the file as a whole corresponding to eGptr(). (???) + +// PUT MODE: +// If a filebuf is in put mode, pbase() is non-NULL and equal to base(). +// Also, epptr() == ebuf(). +// Also, eback() == gptr() && gptr() == egptr(). +// The un-flushed character are those between pbase() and pptr(). +// GET MODE: +// If a filebuf is in get or putback mode, eback() != egptr(). +// In get mode, the unread characters are between gptr() and egptr(). +// The OS file position corresponds to that of egptr(). +// PUTBACK MODE: +// Putback mode is used to remember "excess" characters that have +// been sputbackc'd in a separate putback buffer. +// In putback mode, the get buffer points to the special putback buffer. +// The unread characters are the characters between gptr() and egptr() +// in the putback buffer, as well as the area between save_gptr() +// and save_egptr(), which point into the original reserve buffer. +// (The pointers save_gptr() and save_egptr() are the values +// of gptr() and egptr() at the time putback mode was entered.) +// The OS position corresponds to that of save_egptr(). +// +// LINE BUFFERED OUTPUT: +// During line buffered output, pbase()==base() && epptr()==base(). +// However, ptr() may be anywhere between base() and ebuf(). +// This forces a call to filebuf::overflow(int C) on every put. +// If there is more space in the buffer, and C is not a '\n', +// then C is inserted, and pptr() incremented. +// +// UNBUFFERED STREAMS: +// If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer. + +#define CLOSED_FILEBUF_FLAGS \ + (_S_IS_FILEBUF+_S_NO_READS+_S_NO_WRITES+_S_TIED_PUT_GET) + +void filebuf::init() +{ + _fb._offset = 0; + + _link_in(); + _fb._fileno = -1; +} + +filebuf::filebuf() : backupbuf(CLOSED_FILEBUF_FLAGS) +{ + init(); +} + +filebuf::filebuf(int fd) : backupbuf(CLOSED_FILEBUF_FLAGS) +{ + init(); + attach(fd); +} + +filebuf::filebuf(int fd, char* p, int len) : backupbuf(CLOSED_FILEBUF_FLAGS) +{ + init(); + attach(fd); + setbuf(p, len); +} + +filebuf::~filebuf() +{ + if (!(xflags() & _S_DELETE_DONT_CLOSE)) + close(); + + _un_link(); +} + +filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot) +{ + if (is_open()) + return NULL; + int posix_mode; + int read_write; + if (mode & ios::app) + mode |= ios::out; + if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) { + posix_mode = O_RDWR; + read_write = 0; + } + else if (mode & ios::out) + posix_mode = O_WRONLY, read_write = _S_NO_READS; + else if (mode & (int)ios::in) + posix_mode = O_RDONLY, read_write = _S_NO_WRITES; + else + posix_mode = 0, read_write = _S_NO_READS+_S_NO_WRITES; + if ((mode & (int)ios::trunc) || mode == (int)ios::out) + posix_mode |= O_TRUNC; + if (mode & ios::app) + posix_mode |= O_APPEND, read_write |= _S_IS_APPENDING; + if (!(mode & (int)ios::nocreate) && mode != ios::in) + posix_mode |= O_CREAT; + if (mode & (int)ios::noreplace) + posix_mode |= O_EXCL; + int fd = ::open(filename, posix_mode, prot); + if (fd < 0) + return NULL; + _fb._fileno = fd; + xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING); + if (mode & (ios::ate|ios::app)) { + if (seekoff(0, ios::end) == EOF) + return NULL; + } + _link_in(); + return this; +} + +filebuf* filebuf::open(const char *filename, const char *mode) +{ + if (is_open()) + return NULL; + int oflags = 0, omode; + int read_write; + int oprot = 0666; + switch (*mode++) { + case 'r': + omode = O_RDONLY; + read_write = _S_NO_WRITES; + break; + case 'w': + omode = O_WRONLY; + oflags = O_CREAT|O_TRUNC; + read_write = _S_NO_READS; + break; + case 'a': + omode = O_WRONLY; + oflags = O_CREAT|O_APPEND; + read_write = _S_NO_READS|_S_IS_APPENDING; + break; + default: + errno = EINVAL; + return NULL; + } + if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) { + omode = O_RDWR; + read_write &= _S_IS_APPENDING; + } + int fdesc = ::open(filename, omode|oflags, oprot); + if (fdesc < 0) + return NULL; + _fb._fileno = fdesc; + xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING); + if (read_write & _S_IS_APPENDING) + if (seekoff(0, ios::end) == EOF) + return NULL; + _link_in(); + return this; +} + +filebuf* filebuf::attach(int fd) +{ + if (is_open()) + return NULL; + _fb._fileno = fd; + xsetflags(0, _S_NO_READS+_S_NO_WRITES); + return this; +} + +streambuf* filebuf::setbuf(char* p, int len) +{ + if (streambuf::setbuf(p, len) == NULL) + return NULL; + setp(_base, _base); + setg(_base, _base, _base); + return this; +} + +int filebuf::overflow(int c) +{ + if (xflags() & _S_NO_WRITES) // SET ERROR + return EOF; + // Allocate a buffer if needed. + if (base() == NULL) { + doallocbuf(); + if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(_base, _base); + else setp(_base, _ebuf); + setg(_base, _base, _base); + _flags |= _S_CURRENTLY_PUTTING; + } + // If currently reading, switch to writing. + else if ((_flags & _S_CURRENTLY_PUTTING) == 0) { + if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(gptr(), gptr()); + else setp(gptr(), ebuf()); + setg(egptr(), egptr(), egptr()); + _flags |= _S_CURRENTLY_PUTTING; + } + if (c == EOF) + return do_flush(); + if (pptr() == ebuf() ) // Buffer is really full + if (do_flush() == EOF) + return EOF; + xput_char(c); + if (unbuffered() || (linebuffered() && c == '\n')) + if (do_flush() == EOF) + return EOF; + return (unsigned char)c; +} + +int filebuf::underflow() +{ +#if 0 + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & __SEOF) + return (EOF); +#endif + + if (xflags() & _S_NO_READS) + return EOF; + if (gptr() < egptr()) + return *(unsigned char*)gptr(); + allocbuf(); + + // FIXME This can/should be moved to __streambuf ?? + if ((xflags() & _S_LINE_BUF) || unbuffered()) { + // Flush all line buffered files before reading. + streambuf::flush_all_linebuffered(); + } + + switch_to_get_mode(); + + _G_ssize_t count = sys_read(base(), ebuf() - base()); + if (count <= 0) { + if (count == 0) + xsetflags(_S_EOF_SEEN); + else + xsetflags(_S_ERR_SEEN), count = 0; + } + setg(base(), base(), base() + count); + setp(base(), base()); + if (count == 0) + return EOF; + if (_fb._offset >= 0) + _fb._offset += count; + return *(unsigned char*)gptr(); +} + +int filebuf::do_write(const char *data, int to_do) +{ + if (to_do == 0) + return 0; + if (xflags() & _S_IS_APPENDING) { + // On a system without a proper O_APPEND implementation, + // you would need to sys_seek(0, ios::end) here, but is + // is not needed nor desirable for Unix- or Posix-like systems. + // Instead, just indicate that offset (before and after) is + // unpredictable. + _fb._offset = -1; + } + else if (egptr() != pbase()) { + long new_pos = sys_seek(pbase()-egptr(), ios::cur); + if (new_pos == -1) + return EOF; + _fb._offset = new_pos; + } + _G_ssize_t count = sys_write(data, to_do); + if (_cur_column) + _cur_column = __adjust_column(_cur_column - 1, data, to_do) + 1; + setg(base(), base(), base()); + if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(base(), base()); + else setp(base(), ebuf()); + return count != to_do ? EOF : 0; +} + +int filebuf::sync() +{ +// char* ptr = cur_ptr(); + if (pptr() > pbase()) + if (do_flush()) return EOF; + if (gptr() != egptr()) { + streampos delta = gptr() - egptr(); + if (in_backup()) + delta -= eGptr() - Gbase(); + _G_fpos_t new_pos = sys_seek(delta, ios::cur); + if (new_pos == EOF) + return EOF; + _fb._offset = new_pos; + setg(eback(), gptr(), gptr()); + } + // FIXME: Cleanup - can this be shared? +// setg(base(), ptr, ptr); + return 0; +} + +streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode) +{ + streampos result, new_offset, delta; + _G_ssize_t count; + + if (mode == 0) // Don't move any pointers. + dir = ios::cur, offset = 0; + + // Flush unwritten characters. + // (This may do an unneeded write if we seek within the buffer. + // But to be able to switch to reading, we would need to set + // egptr to ptr. That can't be done in the current design, + // which assumes file_ptr() is eGptr. Anyway, since we probably + // end up flushing when we close(), it doesn't make much difference.) + if (pptr() > pbase() || put_mode()) + if (switch_to_get_mode()) return EOF; + + if (base() == NULL) { + doallocbuf(); + setp(base(), base()); + setg(base(), base(), base()); + } + switch (dir) { + case ios::cur: + if (_fb._offset < 0) { + _fb._offset = sys_seek(0, ios::cur); + if (_fb._offset < 0) + return EOF; + } + // Make offset absolute, assuming current pointer is file_ptr(). + offset += _fb._offset; + + offset -= _egptr - _gptr; + if (in_backup()) + offset -= _other_egptr - _other_gbase; + dir = ios::beg; + break; + case ios::beg: + break; + case ios::end: + struct stat st; + if (sys_stat(&st) == 0 && S_ISREG(st.st_mode)) { + offset += st.st_size; + dir = ios::beg; + } + else + goto dumb; + } + // At this point, dir==ios::beg. + + // If destination is within current buffer, optimize: + if (_fb._offset >= 0 && _eback != NULL) { + // Offset relative to start of main get area. + _G_fpos_t rel_offset = offset - _fb._offset + + (eGptr()-Gbase()); + if (rel_offset >= 0) { + if (in_backup()) + switch_to_main_get_area(); + if (rel_offset <= _egptr - _eback) { + setg(base(), base() + rel_offset, egptr()); + setp(base(), base()); + return offset; + } + // If we have streammarkers, seek forward by reading ahead. + if (have_markers()) { + int to_skip = rel_offset - (_gptr - _eback); + if (ignore(to_skip) != to_skip) + goto dumb; + return offset; + } + } + if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) { + if (!in_backup()) + switch_to_backup_area(); + gbump(_egptr + rel_offset - gptr()); + return offset; + } + } + + unsave_markers(); + + // Try to seek to a block boundary, to improve kernel page management. + new_offset = offset & ~(ebuf() - base() - 1); + delta = offset - new_offset; + if (delta > ebuf() - base()) { + new_offset = offset; + delta = 0; + } + result = sys_seek(new_offset, ios::beg); + if (result < 0) + return EOF; + if (delta == 0) + count = 0; + else { + count = sys_read(base(), ebuf()-base()); + if (count < delta) { + // We weren't allowed to read, but try to seek the remainder. + offset = count == EOF ? delta : delta-count; + dir = ios::cur; + goto dumb; + } + } + setg(base(), base()+delta, base()+count); + setp(base(), base()); + _fb._offset = result + count; + xflags(xflags() & ~ _S_EOF_SEEN); + return offset; + dumb: + unsave_markers(); + result = sys_seek(offset, dir); + if (result != EOF) { + xflags(xflags() & ~_S_EOF_SEEN); + } + _fb._offset = result; + setg(base(), base(), base()); + setp(base(), base()); + return result; +} + +filebuf* filebuf::close() +{ + if (!is_open()) + return NULL; + + // This flushes as well as switching mode. + if (pptr() > pbase() || put_mode()) + if (switch_to_get_mode()) return NULL; + + unsave_markers(); + + int status = sys_close(); + + // Free buffer. + setb(NULL, NULL, 0); + setg(NULL, NULL, NULL); + setp(NULL, NULL); + + _un_link(); + _flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS; + _fb._fileno = EOF; + _fb._offset = 0; + + return status < 0 ? NULL : this; +} + +_G_ssize_t filebuf::sys_read(char* buf, size_t size) +{ + for (;;) { + _G_ssize_t count = ::read(_fb._fileno, buf, size); + if (count != -1 || errno != EINTR) + return count; + } +} + +_G_fpos_t filebuf::sys_seek(_G_fpos_t offset, _seek_dir dir) +{ + return ::lseek(fd(), offset, (int)dir); +} + +_G_ssize_t filebuf::sys_write(const void *buf, long n) +{ + long to_do = n; + while (to_do > 0) { + _G_ssize_t count = ::write(fd(), buf, to_do); + if (count == EOF) { + if (errno == EINTR) + continue; + else { + _flags |= _S_ERR_SEEN; + break; + } + } + to_do -= count; + buf = (void*)((char*)buf + count); + } + n -= to_do; + if (_fb._offset >= 0) + _fb._offset += n; + return n; +} + +int filebuf::sys_stat(void* st) +{ + return ::_fstat(fd(), (struct stat*)st); +} + +int filebuf::sys_close() +{ + return ::close(fd()); +} + +int filebuf::xsputn(const char *s, int n) +{ + if (n <= 0) + return 0; + // This is an optimized implementation. + // If the amount to be written straddles a block boundary + // (or the filebuf is unbuffered), use sys_write directly. + + int to_do = n; + int must_flush = 0; + // First figure out how much space is available in the buffer. + int count = _epptr - _pptr; // Space available. + if (linebuffered() && (_flags & _S_CURRENTLY_PUTTING)) { + count =_ebuf - _pptr; + if (count >= n) { + for (register const char *p = s + n; p > s; ) { + if (*--p == '\n') { + count = p - s + 1; + must_flush = 1; + break; + } + } + } + } + // Then fill the buffer. + if (count > 0) { + if (count > to_do) + count = to_do; + if (count > 20) { + memcpy(pptr(), s, count); + s += count; + } + else { + register char *p = pptr();; + for (register int i = count; --i >= 0; ) *p++ = *s++; + } + pbump(count); + to_do -= count; + } + if (to_do + must_flush > 0) { + // Next flush the (full) buffer. + if (__overflow(this, EOF) == EOF) + return n - to_do; + + // Try to maintain alignment: write a whole number of blocks. + // dont_write is what gets left over. + int block_size = _ebuf - _base; + int dont_write = block_size >= 128 ? to_do % block_size : 0; + + _G_ssize_t count = to_do - dont_write; + if (do_write(s, count) == EOF) + return n - to_do; + to_do = dont_write; + + // Now write out the remainder. Normally, this will fit in the + // buffer, but it's somewhat messier for line-buffered files, + // so we let streambuf::sputn handle the general case. + if (dont_write) + to_do -= streambuf::sputn(s+count, dont_write); + } + return n - to_do; +} + +int filebuf::xsgetn(char *s, int n) +{ + // FIXME: OPTIMIZE THIS (specifically, when unbuffered()). + return streambuf::xsgetn(s, n); +} + +// Non-ANSI AT&T-ism: Default open protection. +const int filebuf::openprot = 0644; diff --git a/gnu/lib/libg++/iostream/floatconv.C b/gnu/lib/libg++/iostream/floatconv.C new file mode 100644 index 00000000000..fb70052c035 --- /dev/null +++ b/gnu/lib/libg++/iostream/floatconv.C @@ -0,0 +1,2416 @@ +#include <ioprivate.h> +#ifdef USE_DTOA +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Some cleaning up by Per Bothner, bothner@cygnus.com, 1992, 1993. */ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define Just_16 to store 16 bits per 32-bit long when doing high-precision + * integer arithmetic. Whether this speeds things up or slows things + * down depends on the machine and the number being converted. + * #define KR_headers for old-style C function headers. + */ + +#ifdef DEBUG +#include <stdio.h> +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#include <stdlib.h> +#include <string.h> +#define CONST const + +#include <errno.h> +#include <float.h> +#ifndef __MATH_H__ +#include <math.h> +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(__i386__) +#define IEEE_8087 +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 + +#if FLT_RADIX==16 +#define IBM +#elif DBL_MANT_DIG==56 +#define VAX +#elif DBL_MANT_DIG==53 && DBL_MAX_10_EXP==308 +#define IEEE_Unknown +#else +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif +#endif + +#ifdef IEEE_8087 +#define HIWORD 1 +#define LOWORD 0 +#define TEST_ENDIANNESS /* nothing */ +#elif defined(IEEE_MC68k) +#define HIWORD 0 +#define LOWORD 1 +#define TEST_ENDIANNESS /* nothing */ +#else +static int HIWORD = -1, LOWORD; +static void test_endianness() +{ + union doubleword { + double d; + unsigned long u[2]; + } dw; + dw.d = 10; + if (dw.u[0] != 0) /* big-endian */ + HIWORD=0, LOWORD=1; + else + HIWORD=1, LOWORD=0; +} +#define TEST_ENDIANNESS if (HIWORD<0) test_endianness(); +#endif +#define word0(x) ((unsigned long *)&x)[HIWORD] +#define word1(x) ((unsigned long *)&x)[LOWORD] + +/* The following definition of Storeinc is appropriate for MIPS processors. */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#elif defined(IEEE_MC68k) +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_Unknown) +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +extern double rnd_prod(double, double), rnd_quot(double, double); +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#ifndef Just_16 +/* When Pack_32 is not defined, we store 16 bits per 32-bit long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per long. + */ +#ifndef Pack_32 +#define Pack_32 +#endif +#endif + +#define Kmax 15 + +extern "C" double _Xstrtod(const char *s00, char **se); +extern "C" char *dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); + +struct Bigint { + /* Note: Order of fields is significant: Cfr. Bcopy macro. */ + struct Bigint *next; + int k; /* Parameter given to Balloc(k) */ + int maxwds; /* Allocated space: equals 1<<k. */ + int sign; + int wds; /* Current length. */ + unsigned long x[1]; /* Actually: x[maxwds] */ +}; + + typedef struct Bigint Bigint; + + static Bigint *freelist[Kmax+1]; + +/* Allocate a Bigint with '1<<k' big digits. */ + + static Bigint * +Balloc +#ifdef KR_headers + (k) int k; +#else + (int k) +#endif +{ + int x; + Bigint *rv; + + if (rv = freelist[k]) { + freelist[k] = rv->next; + } + else { + x = 1 << k; + rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long)); + rv->k = k; + rv->maxwds = x; + } + rv->sign = rv->wds = 0; + return rv; + } + + static void +Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + if (v) { + v->next = freelist[v->k]; + freelist[v->k] = v; + } + } + +#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ +y->wds*sizeof(long) + 2*sizeof(int)) + +/* Return b*m+a. b is modified. */ + + static Bigint * +multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (Bigint *b, int m, int a) +#endif +{ + int i, wds; + unsigned long *x, y; +#ifdef Pack_32 + unsigned long xi, z; +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + do { +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int)(z >> 16); + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + a; + a = (int)(y >> 16); + *x++ = y & 0xffff; +#endif + } + while(++i < wds); + if (a) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = a; + b->wds = wds; + } + return b; + } + + static Bigint * +s2b +#ifdef KR_headers + (s, nd0, nd, y9) CONST char *s; int nd0, nd; unsigned long y9; +#else + (CONST char *s, int nd0, int nd, unsigned long y9) +#endif +{ + Bigint *b; + int i, k; + long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; + } + + static int +hi0bits +#ifdef KR_headers + (x) register unsigned long x; +#else + (register unsigned long x) +#endif +{ + register int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + + static int +lo0bits +#ifdef KR_headers + (y) unsigned long *y; +#else + (unsigned long *y) +#endif +{ + register int k; + register unsigned long x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x & 1) + return 32; + } + *y = x; + return k; + } + + static Bigint * +i2b +#ifdef KR_headers + (i) int i; +#else + (int i) +#endif +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; + } + + static Bigint * +mult +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int k, wa, wb, wc; + unsigned long carry, y, z; + unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0; +#ifdef Pack_32 + unsigned long z2; +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if (y = *xb & 0xffff) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if (y = *xb >> 16) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while(x < xae); + *xc = carry; + } + } +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + + static Bigint *p5s; + +/* Returns b*(5**k). b is modified. */ + + static Bigint * +pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if (i = k & 3) + b = multadd(b, p05[i-1], 0); + + if (!(k >>= 2)) + return b; + if (!(p5 = p5s)) { + /* first time */ + p5 = p5s = i2b(625); + p5->next = 0; + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + p51->next = 0; + } + p5 = p51; + } + return b; + } + + static Bigint * +lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + int i, k1, n, n1; + Bigint *b1; + unsigned long *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) { + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#else + if (k &= 0xf) { + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#endif + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; + } + + static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + unsigned long *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + + static Bigint * +diff +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int i, wa, wb; + long borrow, y; /* We need signed shifts here. */ + unsigned long *xa, *xae, *xb, *xbe, *xc; +#ifdef Pack_32 + long z; +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + + static double +ulp +#ifdef KR_headers + (x) double x; +#else + (double x) +#endif +{ + register long L; + double a; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0(a) = L; + word1(a) = 0; +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(a) = 0x80000 >> L; + word1(a) = 0; + } + else { + word0(a) = 0; + L -= Exp_shift; + word1(a) = L >= 31 ? 1 : 1 << 31 - L; + } + } +#endif + return a; + } + + static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + unsigned long *xa, *xa0, w, y, z; + int k; + double d; +#ifdef VAX + unsigned long d0, d1; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + d0 = Exp_1 | y >> Ebits - k; + w = xa > xa0 ? *--xa : 0; + d1 = y << (32-Ebits) + k | w >> Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> 32 - k; + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> 32 - k; + } + else { + d0 = Exp_1 | y; + d1 = z; + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; + y = xa > xa0 ? *--xa : 0; + d1 = w << k + 16 | y << k; +#endif + ret_d: +#ifdef VAX + word0(d) = d0 >> 16 | d0 << 16; + word1(d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return d; + } + + static Bigint * +d2b +#ifdef KR_headers + (d, e, bits) double d; int *e, *bits; +#else + (double d, int *e, int *bits) +#endif +{ + Bigint *b; + int de, i, k; + unsigned long *x, y, z; +#ifdef VAX + unsigned long d0, d1; + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ + + de = (int)(d0 >> Exp_shift); /* The exponent part of d. */ + + /* Put back the suppressed high-order bit, if normalized. */ +#ifndef IBM +#ifndef Sudden_Underflow + if (de) +#endif + z |= Exp_msk1; +#endif + +#ifdef Pack_32 + if (y = d1) { + if (k = lo0bits(&y)) { + x[0] = y | z << 32 - k; + z >>= k; + } + else + x[0] = y; + i = b->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; + i = b->wds = 1; + k += 32; + } +#else + if (y = d1) { + if (k = lo0bits(&y)) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; + } +#undef d0 +#undef d1 + + static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + double da, db; + int k, ka, kb; + + da = b2d(a, &ka); + db = b2d(b, &kb); +#ifdef Pack_32 + k = ka - kb + 32*(a->wds - b->wds); +#else + k = ka - kb + 16*(a->wds - b->wds); +#endif +#ifdef IBM + if (k > 0) { + word0(da) += (k >> 2)*Exp_msk1; + if (k &= 3) + da *= 1 << k; + } + else { + k = -k; + word0(db) += (k >> 2)*Exp_msk1; + if (k &= 3) + db *= 1 << k; + } +#else + if (k > 0) + word0(da) += k*Exp_msk1; + else { + k = -k; + word0(db) += k*Exp_msk1; + } +#endif + return da / db; + } + + static double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + + static double +#ifdef IEEE_Arith +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; +#define n_bigtens 5 +#else +#ifdef IBM +bigtens[] = { 1e16, 1e32, 1e64 }; +static double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +bigtens[] = { 1e16, 1e32 }; +static double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + + double +_Xstrtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (CONST char *s00, char **se) +#endif +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1, adj, rv, rv0; + long L; + unsigned long y, z; + Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; + TEST_ENDIANNESS; + sign = nz0 = nz = 0; + rv = 0.; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + goto ret; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + if (c == '.') { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + e = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + e = 10*e + c - '0'; + if (s - s1 > 8) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 9999999; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + rv = y; + if (k > 9) + rv = tens[k - 9] * rv + z; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else + /* rv = */ rounded_product(rv, tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + rv *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0(rv) -= P*Exp_msk1; + /* rv = */ rounded_product(rv, tens[e]); + if ((word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + word0(rv) += P*Exp_msk1; +#else + /* rv = */ rounded_product(rv, tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* rv = */ rounded_quotient(rv, tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if (i = e1 & 15) + rv *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: + errno = ERANGE; +#ifndef HUGE_VAL +#define HUGE_VAL 1.7976931348623157E+308 +#endif + rv = HUGE_VAL; + goto ret; + } + if (e1 >>= 4) { + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= bigtens[j]; + /* The last multiplication could overflow. */ + word0(rv) -= P*Exp_msk1; + rv *= bigtens[j]; + if ((z = word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0(rv) = Big0; + word1(rv) = Big1; + } + else + word0(rv) += P*Exp_msk1; + } + + } + } + else if (e1 < 0) { + e1 = -e1; + if (i = e1 & 15) + rv /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= tinytens[j]; + /* The last multiplication could underflow. */ + rv0 = rv; + rv *= tinytens[j]; + if (!rv) { + rv = 2.*rv0; + rv *= tinytens[j]; + if (!rv) { + undfl: + rv = 0.; + errno = ERANGE; + goto ret; + } + word0(rv) = Tiny0; + word1(rv) = Tiny1; + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(s0, nd0, nd, y); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j = bbe + (P-Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) + break; + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((word0(rv) & Bndry_mask1) == Bndry_mask1 + && word1(rv) == 0xffffffff) { + /*boundary case -- increment exponent*/ + word0(rv) = (word0(rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; + word1(rv) = 0; + break; + } + } + else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = word0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (word0(rv) & Exp_mask) - Exp_msk1; +#endif + word0(rv) = L | Bndry_mask1; + word1(rv) = 0xffffffff; +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(rv) & LSB)) + break; +#endif + if (dsign) + rv += ulp(rv); +#ifndef ROUND_BIASED + else { + rv -= ulp(rv); +#ifndef Sudden_Underflow + if (!rv) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (word1(rv) || word0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(rv) == Tiny1 && !word0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(FLT_ROUNDS) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = word0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + rv0 = rv; + word0(rv) -= P*Exp_msk1; + adj = aadj1 * ulp(rv); + rv += adj; + if ((word0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(rv0) == Big0 && word1(rv0) == Big1) + goto ovfl; + word0(rv) = Big0; + word1(rv) = Big1; + goto cont; + } + else + word0(rv) += P*Exp_msk1; + } + else { +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + rv0 = rv; + word0(rv) += P*Exp_msk1; + adj = aadj1 * ulp(rv); + rv += adj; +#ifdef IBM + if ((word0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(rv0) == Tiny0 + && word1(rv0) == Tiny1) + goto undfl; + word0(rv) = Tiny0; + word1(rv) = Tiny1; + goto cont; + } + else + word0(rv) -= P*Exp_msk1; + } + else { + adj = aadj1 * ulp(rv); + rv += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(rv); + rv += adj; +#endif + } + z = word0(rv) & Exp_mask; + if (y == z) { + /* Can we stop now? */ + L = (long)aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + cont: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + ret: + if (se) + *se = (char *)s; + return sign ? -rv : rv; + } + + static int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + long borrow, y; + unsigned long carry, q, ys; + unsigned long *bx, *bxe, *sx, *sxe; +#ifdef Pack_32 + long z; + unsigned long si, zs; +#endif + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; + } + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the long + * calculation. + */ + + char * +dtoa +#ifdef KR_headers + (d, mode, ndigits, decpt, sign, rve) + double d; int mode, ndigits, *decpt, *sign; char **rve; +#else + (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) +#endif +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + long L; +#ifndef Sudden_Underflow + int denorm; + unsigned long x; +#endif + Bigint *b, *b1, *delta, *mlo, *mhi, *S; + double d2, ds, eps; + char *s, *s0; + static Bigint *result; + static int result_k; + + TEST_ENDIANNESS; + if (result) { + result->k = result_k; + result->maxwds = 1 << result_k; + Bfree(result); + result = 0; + } + + if (word0(d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0(d) & Exp_mask) == Exp_mask) +#else + if (word0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; +#ifdef IEEE_Arith + if (!word1(d) && !(word0(d) & 0xfffff)) + { + s = "Infinity"; + if (*rve) + *rve = s + 8; + } + else +#endif + { + s = "NaN"; + if (rve) + *rve = s +3; + } + return s; + } +#endif +#ifdef IBM + d += 0; /* normalize */ +#endif + if (!d) { + *decpt = 1; + s = "0"; + if (rve) + *rve = s + 1; + return s; + } + + b = d2b(d, &be, &bbits); + i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#ifndef Sudden_Underflow + if (i) { +#endif + d2 = d; + word0(d2) &= Frac_mask1; + word0(d2) |= Exp_11; +#ifdef IBM + if (j = 11 - hi0bits(word0(d2) & Frac_mask)) + d2 /= 1 << j; +#endif + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 + : word1(d) << 32 - i; + d2 = x; + word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + + /* Now i is the unbiased base-2 exponent. */ + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = i*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = i*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i) by 0.301029995663981; since |i| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch(mode) { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + /* i is now an upper bound of the number of digits to generate. */ + j = sizeof(unsigned long); + /* The test is <= so as to allow room for the final '\0'. */ + for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j <= i; + j <<= 1) result_k++; + result = Balloc(result_k); + s = s0 = (char *)result; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + d /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + d /= ds; + } + else if (j1 = -k) { + d *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + d *= bigtens[i]; + } + } + if (k_check && d < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d *= 10.; + ieps++; + } + eps = ieps*d + 7.; + word0(eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + d -= 5.; + if (d > eps) + goto one_digit; + if (d < -eps) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + eps = 0.5/tens[ilim-1] - eps; + for(i = 0;;) { + L = (long)d; + d -= L; + *s++ = '0' + (int)L; + if (d < eps) + goto ret1; + if (1. - d < eps) + goto bump_up; + if (++i >= ilim) + break; + eps *= 10.; + d *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + eps *= tens[ilim-1]; + for(i = 1;; i++, d *= 10.) { + L = (long)d; + d -= L; + *s++ = '0' + (int)L; + if (i == ilim) { + if (d > 0.5 + eps) + goto bump_up; + else if (d < 0.5 - eps) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || d <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++) { + L = (long)(d / ds); + d -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d < 0) { + L--; + d += ds; + } +#endif + *s++ = '0' + (int)L; + if (i == ilim) { + d += d; + if (d > ds || d == ds && L & 1) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if (!(d *= 10.)) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + if (mode < 2) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + } + else { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if (j = b5 - m5) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) { + if (!word1(d) && !(word0(d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(d) & Exp_mask +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ +#ifdef Pack_32 + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) + i = 32 - i; +#else + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) + i = 16 - i; +#endif + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j1 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(word1(d) & 1)) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || j == 0 && !mode +#ifndef ROUND_BIASED + && !(word1(d) & 1) +#endif + ) { + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || j1 == 0 && dig & 1) + && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j1 > 0) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || j == 0 && dig & 1) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + while(*--s == '0'); + s++; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; + } +#endif /* USE_DTOA */ diff --git a/gnu/lib/libg++/iostream/floatio.h b/gnu/lib/libg++/iostream/floatio.h new file mode 100644 index 00000000000..d3d2d0e5201 --- /dev/null +++ b/gnu/lib/libg++/iostream/floatio.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: floatio.h,v 1.1 1995/10/18 08:38:12 deraadt Exp $ + */ + +/* + * Floating point scanf/printf (input/output) definitions. + */ + +/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ +#define MAXEXP 308 +/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ +#define MAXFRACT 39 diff --git a/gnu/lib/libg++/iostream/fstream.C b/gnu/lib/libg++/iostream/fstream.C new file mode 100644 index 00000000000..9b45573ea03 --- /dev/null +++ b/gnu/lib/libg++/iostream/fstream.C @@ -0,0 +1,65 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include "ioprivate.h" +#include <fstream.h> + +fstreambase::fstreambase() +{ + init(new filebuf()); +} + +fstreambase::fstreambase(int fd) +{ + init(new filebuf(fd)); +} + +fstreambase::fstreambase(const char *name, int mode, int prot) +{ + init(new filebuf()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +void fstreambase::open(const char *name, int mode, int prot) +{ + clear(); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +void fstreambase::close() +{ + if (!rdbuf()->close()) + set(ios::failbit); +} + +#if 0 +static int mode_to_sys(enum open_mode mode) +{ + return O_WRONLY; +} + +static char* fopen_cmd_arg(io_mode i) +{ + return "w"; +} +#endif diff --git a/gnu/lib/libg++/iostream/fstream.h b/gnu/lib/libg++/iostream/fstream.h new file mode 100644 index 00000000000..7395dc8b878 --- /dev/null +++ b/gnu/lib/libg++/iostream/fstream.h @@ -0,0 +1,72 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: fstream.h,v 1.1 1995/10/18 08:38:12 deraadt Exp $ + +#ifndef _FSTREAM_H +#define _FSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <iostream.h> + +class fstreambase : virtual public ios { + public: + fstreambase(); + fstreambase(int fd); + fstreambase(const char *name, int mode, int prot=0664); + void close(); + filebuf* rdbuf() const { return (filebuf*)_strbuf; } + void open(const char *name, int mode, int prot=0664); + int is_open() const { return rdbuf()->is_open(); } + void setbuf(char *ptr, int len) { rdbuf()->setbuf(ptr, len); } +#ifdef _STREAM_COMPAT + int filedesc() { return rdbuf()->fd(); } + fstreambase& raw() { rdbuf()->setbuf(NULL, 0); return *this; } +#endif +}; + +class ifstream : public fstreambase, public istream { + public: + ifstream() : fstreambase() { } + ifstream(int fd) : fstreambase(fd) { } + ifstream(const char *name, int mode=ios::in, int prot=0664) + : fstreambase(name, mode, prot) { } + void open(const char *name, int mode=ios::in, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; + +class ofstream : public fstreambase, public ostream { + public: + ofstream() : fstreambase() { } + ofstream(int fd) : fstreambase(fd) { } + ofstream(const char *name, int mode=ios::out, int prot=0664) + : fstreambase(name, mode, prot) { } + void open(const char *name, int mode=ios::out, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; + +class fstream : public fstreambase, public iostream { + public: + fstream() : fstreambase() { } + fstream(int fd) : fstreambase(fd) { } + fstream(const char *name, int mode, int prot=0664) + : fstreambase(name, mode, prot) { } + void open(const char *name, int mode, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; +#endif /*!_FSTREAM_H*/ diff --git a/gnu/lib/libg++/iostream/igetline.C b/gnu/lib/libg++/iostream/igetline.C new file mode 100644 index 00000000000..90ed189feaf --- /dev/null +++ b/gnu/lib/libg++/iostream/igetline.C @@ -0,0 +1,135 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "iostream.h" +#include <string.h> + +istream& istream::getline(char* buf, int len, char delim) +{ + _gcount = 0; + if (ipfx1()) { + streambuf *sb = rdbuf(); + long count = sb->sgetline(buf, len, delim, -1); + if (count == len-1) + set(ios::failbit); + else { + int ch = sb->sbumpc(); + if (ch == EOF) + set(ios::failbit|ios::eofbit); + else if (ch == (unsigned char)delim) + count++; + else + sb->sungetc(); // Leave delimiter unread. + } + _gcount = count; + } + return *this; +} + +istream& istream::get(char* buf, int len, char delim) +{ + _gcount = 0; + if (ipfx1()) { + streambuf *sbuf = rdbuf(); + long count = sbuf->sgetline(buf, len, delim, -1); + if (count < 0 || (count == 0 && sbuf->sgetc() == EOF)) + set(ios::failbit|ios::eofbit); + else + _gcount = count; + } + return *this; +} + +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Free Software Foundation. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +// from Doug Schmidt + +#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 *_sb_readline (streambuf *sb, long& total, char terminator) +{ + char buf[CHUNK_SIZE+1]; + char *ptr; + int ch; + + long count = sb->sgetline(buf, CHUNK_SIZE+1, terminator, -1); + if (count == EOF) + return NULL; + ch = sb->sbumpc(); + long old_total = total; + total += count; + if (ch != EOF && ch != terminator) { + total++; // Include ch in total. + ptr = _sb_readline(sb, total, terminator); + if (ptr) { + memcpy(ptr + old_total, buf, count); + ptr[old_total+count] = ch; + } + return ptr; + } + + if (ptr = new char[total+1]) { + ptr[total] = '\0'; + memcpy(ptr + total - count, buf, count); + 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 delim /* = '\n' */) +{ + if (ipfx1()) { + long size = 0; + streambuf *sb = rdbuf(); + *s = _sb_readline (sb, size, delim); + _gcount = *s ? size : 0; + if (sb->_flags & _S_EOF_SEEN) { + set(ios::eofbit); + if (_gcount == 0) + set(ios::failbit); + } + } + else { + _gcount = 0; + *s = NULL; + } + return *this; +} diff --git a/gnu/lib/libg++/iostream/igetsb.C b/gnu/lib/libg++/iostream/igetsb.C new file mode 100644 index 00000000000..a6a2e6315d6 --- /dev/null +++ b/gnu/lib/libg++/iostream/igetsb.C @@ -0,0 +1,48 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" +#include "iostream.h" + +istream& istream::get(streambuf& sb, char delim /* = '\n' */) +{ + _gcount = 0; + if (ipfx1()) { + register streambuf* isb = rdbuf(); + for (;;) { + int len = isb->egptr() - isb->gptr(); + if (len <= 0) + if (isb->underflow() == EOF) + break; + else + len = isb->egptr() - isb->gptr(); + char *delimp = (char*)memchr((void*)isb->gptr(), delim, len); + if (delimp != NULL) + len = delimp - isb->gptr(); + int written = sb.sputn(isb->gptr(), len); + isb->gbump(written); + _gcount += written; + if (written != len) { + set(ios::failbit); + break; + } + if (delimp != NULL) + break; + } + } + return *this; +} diff --git a/gnu/lib/libg++/iostream/indstream.C b/gnu/lib/libg++/iostream/indstream.C new file mode 100644 index 00000000000..b58e362d4bd --- /dev/null +++ b/gnu/lib/libg++/iostream/indstream.C @@ -0,0 +1,108 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <indstream.h> + +indirectbuf::indirectbuf(streambuf *get, streambuf *put, int delete_mode) +: streambuf() +{ + _get_stream = get; + _put_stream = put == NULL ? get : put; + _delete_flags = delete_mode; +} + +indirectbuf::~indirectbuf() +{ + if (_delete_flags & ios::in) delete get_stream(); + if (_delete_flags & ios::out) delete put_stream(); +} + +int indirectbuf::xsputn(const char* s, int n) +{ + return put_stream()->sputn(s, n); +} + +int indirectbuf::xsgetn(char* s, int n) +{ + return get_stream()->sgetn(s, n); +} + +int indirectbuf::overflow(int c /* = EOF */) +{ + if (c == EOF) + return put_stream()->overflow(c); + else + return put_stream()->sputc(c); +} + +int indirectbuf::underflow() +{ + return get_stream()->sbumpc(); +} + +streampos indirectbuf::seekoff(streamoff off, _seek_dir dir, int mode) +{ + int ret_val = 0; + int select = mode == 0 ? (ios::in|ios::out) : mode; + streambuf *gbuf = (select & ios::in) ? get_stream() : NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : NULL; + if (gbuf == pbuf) + ret_val = gbuf->seekoff(off, dir, mode); + else { + if (gbuf) + ret_val = gbuf->seekoff(off, dir, ios::in); + if (pbuf && ret_val != EOF) + ret_val = pbuf->seekoff(off, dir, ios::out); + } + return ret_val; +} + +streampos indirectbuf::seekpos(streampos pos, int mode) +{ + int ret_val = EOF; + int select = mode == 0 ? (ios::in|ios::out) : mode; + streambuf *gbuf = (select & ios::in) ? get_stream() : NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : NULL; + if (gbuf == pbuf) + ret_val = gbuf->seekpos(pos, mode); + else { + if (gbuf) + ret_val = gbuf->seekpos(pos, ios::in); + if (pbuf && ret_val != EOF) + ret_val = pbuf->seekpos(pos, ios::out); + } + return ret_val; +} + +int indirectbuf::sync() +{ + streambuf *gbuf = get_stream(); + int ret_val = gbuf->sync(); + if (ret_val == EOF) return ret_val; + streambuf *pbuf = put_stream(); + if (pbuf != gbuf) return pbuf->sync(); + else return ret_val; +} + +int indirectbuf::pbackfail(int c) +{ + return get_stream()->sputbackc(c); +} diff --git a/gnu/lib/libg++/iostream/indstream.h b/gnu/lib/libg++/iostream/indstream.h new file mode 100644 index 00000000000..5c3febe6b37 --- /dev/null +++ b/gnu/lib/libg++/iostream/indstream.h @@ -0,0 +1,67 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: indstream.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#ifndef _INDSTREAM_H +#define _INDSTREAM_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include <iostream.h> + +// An indirectbuf is one that forwards all of its I/O requests +// to another streambuf. +// All get-related requests are sent to get_stream(). +// All put-related requests are sent to put_stream(). + +// An indirectbuf can be used to implement Common Lisp +// synonym-streams and two-way-streams. +// +// class synonymbuf : public indirectbuf { +// Symbol *sym; +// synonymbuf(Symbol *s) { sym = s; } +// virtual streambuf *lookup_stream(int mode) { +// return coerce_to_streambuf(lookup_value(sym)); } +// }; + +class indirectbuf : public streambuf { + protected: + streambuf *_get_stream; // Optional cache for get_stream(). + streambuf *_put_stream; // Optional cache for put_stream(). + int _delete_flags; + public: + streambuf *get_stream() + { return _get_stream ? _get_stream : lookup_stream(ios::in); } + streambuf *put_stream() + { return _put_stream ? _put_stream : lookup_stream(ios::out); } + virtual streambuf *lookup_stream(int/*mode*/) { return NULL; } // ERROR! + indirectbuf(streambuf *get=NULL, streambuf *put=NULL, int delete_mode=0); + virtual ~indirectbuf(); + virtual int xsputn(const char* s, int n); + virtual int xsgetn(char* s, int n); + virtual int underflow(); + virtual int overflow(int c = EOF); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); + virtual int sync(); + virtual int pbackfail(int c); +}; + +#endif /* !_INDSTREAM_H */ diff --git a/gnu/lib/libg++/iostream/iomanip.C b/gnu/lib/libg++/iostream/iomanip.C new file mode 100644 index 00000000000..b2aec86396b --- /dev/null +++ b/gnu/lib/libg++/iostream/iomanip.C @@ -0,0 +1,77 @@ +// -*- C++ -*- +// This is part of the iostream library, providing parametrized manipulators +// Written by Heinz G. Seidl, Copyright (C) 1992 Cygnus Support +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +//#pragma implementation +#endif + +#include "iomanip.h" + + +// Those functions are called through a pointer, +// thus it does not make sense, to inline them. + +ios & __iomanip_setbase (ios& i, int n) +{ + ios::fmtflags b; + switch (n) + { + case 8: + b = ios::oct; break; + case 10: + b = ios::dec; break; + case 16: + b = ios::hex; break; + default: + b = 0; + } + i.setf(b, ios::basefield); + return i; +} + +ios & __iomanip_setfill (ios& i, int n) +{ + //FIXME if ( i.flags() & ios::widechar ) + i.fill( (char) n); + //FIXME else + //FIXME i.fill( (wchar) n); + return i; +} + +ios & __iomanip_setprecision (ios& i, int n) +{ + i.precision(n); + return i; +} +ios & __iomanip_setw (ios& i, int n) +{ + i.width(n); + return i; +} + +ios & __iomanip_setiosflags (ios& i, ios::fmtflags n) +{ + i.setf(n,n); + return i; +} + +ios & __iomanip_resetiosflags (ios& i, ios::fmtflags n) +{ + i.setf(0,n); + return i; +} diff --git a/gnu/lib/libg++/iostream/iomanip.h b/gnu/lib/libg++/iostream/iomanip.h new file mode 100644 index 00000000000..25589a3f9f1 --- /dev/null +++ b/gnu/lib/libg++/iostream/iomanip.h @@ -0,0 +1,152 @@ +// -*- C++ -*- +// This is part of the iostream library, providing parametrized manipulators +// Written by Heinz G. Seidl, Copyright (C) 1992 Cygnus Support +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: iomanip.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#ifndef _IOMANIP_H +// +// Not specifying `pragma interface' causes the compiler to emit the +// template definitions in the files, where they are used. +// +//#ifdef __GNUG__ +//#pragma interface +//#endif +#define _IOMANIP_H + +#include <_G_config.h> + +#ifndef _G_NO_TEMPLATES + +#include <iostream.h> + +//----------------------------------------------------------------------------- +// Parametrized Manipulators as specified by ANSI draft +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class smanip; // TP = Type Param + +template<class TP> class sapp { + ios& (*_f)(ios&, TP); +public: + sapp(ios& (*f)(ios&, TP)) : _f(f) {} + // + smanip<TP> operator()(TP a) + { return smanip<TP>(_f, a); } +}; + +template <class TP> class smanip { + ios& (*_f)(ios&, TP); + TP _a; +public: + smanip(ios& (*f)(ios&, TP), TP a) : _f(f), _a(a) {} + // + friend + istream& operator>>(istream& i, const smanip<TP>& m); + friend + ostream& operator<<(ostream& o, const smanip<TP>& m); +}; + +template<class TP> +inline istream& operator>>(istream& i, const smanip<TP>& m) + { (*m._f)(i, m._a); return i; } + +template<class TP> +inline ostream& operator<<(ostream& o, const smanip<TP>& m) + { (*m._f)(o, m._a); return o;} + +//----------------------------------------------------------------------------- +// Input-Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class imanip; + +template<class TP> class iapp { + istream& (*_f)(istream&, TP); +public: + iapp(ostream& (*f)(istream&,TP)) : _f(f) {} + // + imanip<TP> operator()(TP a) + { return imanip<TP>(_f, a); } +}; + +template <class TP> class imanip { + istream& (*_f)(istream&, TP); + TP _a; +public: + imanip(istream& (*f)(istream&, TP), TP a) : _f(f), _a(a) {} + // + friend + istream& operator>>(istream& i, const imanip<TP>& m) + { return (*m._f)( i, m._a); } +}; + + +//----------------------------------------------------------------------------- +// Output-Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class omanip; + +template<class TP> class oapp { + ostream& (*_f)(ostream&, TP); +public: + oapp(ostream& (*f)(ostream&,TP)) : _f(f) {} + // + omanip<TP> operator()(TP a) + { return omanip<TP>(_f, a); } +}; + +template <class TP> class omanip { + ostream& (*_f)(ostream&, TP); + TP _a; +public: + omanip(ostream& (*f)(ostream&, TP), TP a) : _f(f), _a(a) {} + // + friend + ostream& operator<<(ostream& o, omanip<TP>& m) + { return (*m._f)(o, m._a); } +}; + + +//----------------------------------------------------------------------------- +// Available Manipulators +//----------------------------------------------------------------------------- + +// +// Macro to define an iomanip function, with one argument +// The underlying function is `__iomanip_<name>' +// +#define __DEFINE_IOMANIP_FN1(type,param,function) \ + extern ios& __iomanip_##function (ios&, param); \ + inline type<param> function (param n) \ + { return type<param> (__iomanip_##function, n); } + +__DEFINE_IOMANIP_FN1( smanip, int, setbase) +__DEFINE_IOMANIP_FN1( smanip, int, setfill) +__DEFINE_IOMANIP_FN1( smanip, int, setprecision) +__DEFINE_IOMANIP_FN1( smanip, int, setw) + +__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, resetiosflags) +__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, setiosflags) + +#endif /*!_G_NO_TEMPLATES*/ +#endif /*!_IOMANIP_H*/ diff --git a/gnu/lib/libg++/iostream/ioprivate.h b/gnu/lib/libg++/iostream/ioprivate.h new file mode 100644 index 00000000000..b8b00c209b0 --- /dev/null +++ b/gnu/lib/libg++/iostream/ioprivate.h @@ -0,0 +1,66 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: ioprivate.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "streambuf.h" +#include <stdarg.h> +#include <stddef.h> + +#define _fstat(x, y) fstat(x,y) +#define _isatty(fd) isatty(fd) + +extern int __cvt_double(double number, register int prec, int flags, + int *signp, int fmtch, char *startp, char *endp); + +/*#define USE_MALLOC_BUF*/ + +#ifndef USE_MALLOC_BUF +#define ALLOC_BUF(size) new char[size] +#define FREE_BUF(ptr) delete [] (ptr) +#else +#define ALLOC_BUF(size) (char*)malloc(size) +#define FREE_BUF(ptr) free(ptr) +#endif + +#define USE_DTOA + +// Advantages: +// - Input gets closest value +// - Output emits string that when read yields identical value. +// - Handles Infinity and NaNs (but not re-readable). +// Disadvantages of dtoa: +// - May not work for all double formats. +// - Big chunck of code. +// - Not reentrant - uses atatic variables freelist, +// result, result_k in dtoa +// (plus initializes p5s, HOWORD, and LOWORD). + +#ifdef USE_DTOA +extern "C" double _Xstrtod(const char *s00, char **se); +#define strtod(s, e) _Xstrtod(s, e) +extern "C" char *dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); +extern int __outfloat(double value, streambuf *sb, char mode, + int width, int precision, __fmtflags flags, + char sign_mode, char fill); +#endif + diff --git a/gnu/lib/libg++/iostream/iostream.C b/gnu/lib/libg++/iostream/iostream.C new file mode 100644 index 00000000000..21e26c57475 --- /dev/null +++ b/gnu/lib/libg++/iostream/iostream.C @@ -0,0 +1,783 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991, 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include "ioprivate.h" +#include <iostream.h> +#include <stdio.h> /* Needed for sprintf */ +#include <ctype.h> +#include <limits.h> +#include "floatio.h" + +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ + +//#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n') + +istream::istream(streambuf *sb, ostream* tied) : ios(sb, tied) +{ + _flags |= ios::dont_close; + _gcount = 0; +} + +int skip_ws(streambuf* sb) +{ + int ch; + for (;;) { + ch = sb->sbumpc(); + if (ch == EOF || !isspace(ch)) + return ch; + } +} + +istream& istream::get(char& c) +{ + if (ipfx1()) { + int ch = _strbuf->sbumpc(); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + _gcount = 0; + } + else { + c = (char)ch; + _gcount = 1; + } + } + return *this; +} + +int istream::peek() +{ + if (!good()) + return EOF; + if (_tie && rdbuf()->in_avail() == 0) + _tie->flush(); + int ch = _strbuf->sgetc(); + if (ch == EOF) + set(ios::eofbit); + return ch; +} + +istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */) +{ + if (ipfx1()) { + register streambuf* sb = _strbuf; + if (delim == EOF) { + _gcount = sb->ignore(n); + return *this; + } + _gcount = 0; + for (;;) { +#if 0 + if (n != MAXINT) // FIXME +#endif + if (--n < 0) + break; + int ch = sb->sbumpc(); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + break; + } + _gcount++; + if (ch == delim) + break; + } + } + return *this; +} + +istream& istream::read(char *s, int n) +{ + if (ipfx1()) { + _gcount = _strbuf->sgetn(s, n); + if (_gcount != n) + set(ios::failbit); + } + return *this; +} + +istream& istream::seekg(streampos pos) +{ + pos = _strbuf->seekpos(pos, ios::in); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +istream& istream::seekg(streamoff off, _seek_dir dir) +{ + streampos pos = _strbuf->seekoff(off, dir, ios::in); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos istream::tellg() +{ + streampos pos = _strbuf->seekoff(0, ios::cur, ios::in); + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +istream& istream::scan(const char *format ...) +{ + if (ipfx0()) { + va_list ap; + va_start(ap, format); + _strbuf->vscan(format, ap, this); + va_end(ap); + } + return *this; +} + +istream& istream::vscan(const char *format, _G_va_list args) +{ + if (ipfx0()) + _strbuf->vscan(format, args, this); + return *this; +} + +istream& istream::operator>>(char& c) +{ + if (ipfx0()) { + int ch = _strbuf->sbumpc(); + if (ch == EOF) + set(ios::eofbit|ios::failbit); + else + c = (char)ch; + } + return *this; +} + +istream& istream::operator>>(char* ptr) +{ + register char *p = ptr; + int w = width(0); + if (ipfx0()) { + register streambuf* sb = _strbuf; + for (;;) + { + int ch = sb->sbumpc(); + if (ch == EOF) + { + set(p == ptr ? (ios::eofbit|ios::failbit) : (ios::eofbit)); + break; + } + else if (isspace(ch)) + { + sb->sputbackc(ch); + break; + } + else if (w == 1) + { + set(ios::failbit); + sb->sputbackc(ch); + break; + } + else *p++ = ch; + w--; + } + } + *p = '\0'; + return *this; +} + +#ifdef __GNUC__ +#define LONGEST long long +#else +#define LONGEST long +#endif + +static int read_int(istream& stream, unsigned LONGEST& val, int& neg) +{ + if (!stream.ipfx0()) + return 0; + register streambuf* sb = stream.rdbuf(); + int base = 10; + int ndigits = 0; + register int ch = skip_ws(sb); + if (ch == EOF) + goto eof_fail; + neg = 0; + if (ch == '+') { + ch = skip_ws(sb); + } + else if (ch == '-') { + neg = 1; + ch = skip_ws(sb); + } + if (ch == EOF) goto eof_fail; + if (!(stream.flags() & ios::basefield)) { + if (ch == '0') { + ch = sb->sbumpc(); + if (ch == EOF) { + val = 0; + return 1; + } + if (ch == 'x' || ch == 'X') { + base = 16; + ch = sb->sbumpc(); + if (ch == EOF) goto eof_fail; + } + else { + sb->sputbackc(ch); + base = 8; + ch = '0'; + } + } + } + else if ((stream.flags() & ios::basefield) == ios::hex) + base = 16; + else if ((stream.flags() & ios::basefield) == ios::oct) + base = 8; + val = 0; + for (;;) { + if (ch == EOF) + break; + int digit; + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = 999; + if (digit >= base) { + sb->sputbackc(ch); + if (ndigits == 0) + goto fail; + else + return 1; + } + ndigits++; + val = base * val + digit; + ch = sb->sbumpc(); + } + return 1; + fail: + stream.set(ios::failbit); + return 0; + eof_fail: + stream.set(ios::failbit|ios::eofbit); + return 0; +} + +#define READ_INT(TYPE) \ +istream& istream::operator>>(TYPE& i)\ +{\ + unsigned LONGEST val; int neg;\ + if (read_int(*this, val, neg)) {\ + if (neg) val = -val;\ + i = (TYPE)val;\ + }\ + return *this;\ +} + +READ_INT(short) +READ_INT(unsigned short) +READ_INT(int) +READ_INT(unsigned int) +READ_INT(long) +READ_INT(unsigned long) +#ifdef __GNUG__ +READ_INT(long long) +READ_INT(unsigned long long) +#endif + +istream& istream::operator>>(double& x) +{ + if (ipfx0()) + scan("%lg", &x); + return *this; +} + +istream& istream::operator>>(float& x) +{ + if (ipfx0()) + scan("%g", &x); + return *this; +} + +istream& istream::operator>>(register streambuf* sbuf) +{ + if (ipfx0()) { + register streambuf* inbuf = rdbuf(); + // FIXME: Should optimize! + for (;;) { + register int ch = inbuf->sbumpc(); + if (ch == EOF) { + set(ios::eofbit); + break; + } + if (sbuf->sputc(ch) == EOF) { + set(ios::failbit); + break; + } + } + } + return *this; +} + +ostream& ostream::operator<<(char c) +{ + if (opfx()) { +#if 1 + // This is what the cfront implementation does. + _strbuf->sputc(c); +#else + // This is what cfront documentation and current ANSI drafts say. + int w = width(0); + char fill_char = fill(); + register int padding = w > 0 ? w - 1 : 0; + register streambuf *sb = _strbuf; + if (!(flags() & ios::left)) // Default adjustment. + while (--padding >= 0) sb->sputc(fill_char); + sb->sputc(c); + if (flags() & ios::left) // Left adjustment. + while (--padding >= 0) sb->sputc(fill_char); +#endif + osfx(); + } + return *this; +} + +/* Write VAL on STREAM. + If SIGN<0, val is the absolute value of a negative number. + If SIGN>0, val is a signed non-negative number. + If SIGN==0, val is unsigned. */ + +static void write_int(ostream& stream, unsigned LONGEST val, int sign) +{ +#define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3) + char buf[WRITE_BUF_SIZE]; + register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf. + char *show_base = ""; + int show_base_len = 0; + int show_pos = 0; // If 1, print a '+'. + + // Now do the actual conversion, placing the result at the *end* of buf. + // Note that we use separate code for decimal, octal, and hex, + // so we can divide by optimizable constants. + if ((stream.flags() & ios::basefield) == ios::oct) { // Octal + do { + *--buf_ptr = (val & 7) + '0'; + val = val >> 3; + } while (val != 0); + if ((stream.flags() & ios::showbase) && (val != 0)) + *--buf_ptr = '0'; + } + else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex + char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X" + : "0123456789abcdef0x"; + do { + *--buf_ptr = xdigs[val & 15]; + val = val >> 4; + } while (val != 0); + if ((stream.flags() & ios::showbase) && (val != 0)) { + show_base = xdigs + 16; // Either "0X" or "0x". + show_base_len = 2; + } + } + else { // Decimal +#ifdef __GNUC__ + // Optimization: Only use long long when we need to. + while (val > UINT_MAX) { + *--buf_ptr = (val % 10) + '0'; + val /= 10; + } + // Use more efficient (int) arithmetic for the rest. + register unsigned int ival = (unsigned int)val; +#else + register unsigned LONGEST ival = val; +#endif + do { + *--buf_ptr = (ival % 10) + '0'; + ival /= 10; + } while (ival != 0); + if (sign > 0 && (stream.flags() & ios::showpos)) + show_pos=1; + } + + int buf_len = buf+WRITE_BUF_SIZE - buf_ptr; + int w = stream.width(0); + + // Calculate padding. + int len = buf_len+show_pos; + if (sign < 0) len++; + len += show_base_len; + int padding = len > w ? 0 : w - len; + + // Do actual output. + register streambuf* sbuf = stream.rdbuf(); + ios::fmtflags pad_kind = + stream.flags() & (ios::left|ios::right|ios::internal); + char fill_char = stream.fill(); + if (padding > 0 + && pad_kind != (ios::fmtflags)ios::left + && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust. + sbuf->padn(fill_char, padding); + if (sign < 0) sbuf->sputc('-'); + else if (show_pos) sbuf->sputc('+'); + if (show_base_len) + sbuf->sputn(show_base, show_base_len); + if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) + sbuf->padn(fill_char, padding); + sbuf->sputn(buf_ptr, buf_len); + if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment + sbuf->padn(fill_char, padding); + stream.osfx(); +} + +ostream& ostream::operator<<(int n) +{ + if (opfx()) { + int sign = 1; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + n = -n, sign = -1; + write_int(*this, n, sign); + } + return *this; +} + +ostream& ostream::operator<<(unsigned int n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} + + +ostream& ostream::operator<<(long n) +{ + if (opfx()) { + int sign = 1; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + n = -n, sign = -1; + write_int(*this, n, sign); + } + return *this; +} + +ostream& ostream::operator<<(unsigned long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} + +#ifdef __GNUG__ +ostream& ostream::operator<<(long long n) +{ + if (opfx()) { + int sign = 1; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + n = -n, sign = -1; + write_int(*this, n, sign); + } + return *this; +} + + +ostream& ostream::operator<<(unsigned long long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} +#endif /*__GNUG__*/ + +ostream& ostream::operator<<(double n) +{ + if (opfx()) { + // Uses __cvt_double (renamed from static cvt), in Chris Torek's + // stdio implementation. The setup code uses the same logic + // as in __vsbprintf.C (also based on Torek's code). + int format_char; +#if 0 + if (flags() ios::showpos) sign = '+'; +#endif + if ((flags() & ios::floatfield) == ios::fixed) + format_char = 'f'; + else if ((flags() & ios::floatfield) == ios::scientific) + format_char = flags() & ios::uppercase ? 'E' : 'e'; + else + format_char = flags() & ios::uppercase ? 'G' : 'g'; + + int fpprec = 0; // 'Extra' (suppressed) floating precision. + int prec = precision(); + if (prec > MAXFRACT) { + if (flags() & (ios::fixed|ios::scientific) & ios::showpos) + fpprec = prec - MAXFRACT; + prec = MAXFRACT; + } + else if (prec <= 0 && !(flags() & ios::fixed)) + prec = 6; /* default */ + + // Do actual conversion. +#ifdef USE_DTOA + if (__outfloat(n, rdbuf(), format_char, width(0), + prec, flags(), 0, fill()) < 0) + set(ios::badbit|ios::failbit); // ?? +#else + int negative; + char buf[BUF]; + int sign = '\0'; + char *cp = buf; + *cp = 0; + int size = __cvt_double(n, prec, + flags() & ios::showpoint ? 0x80 : 0, + &negative, + format_char, cp, buf + sizeof(buf)); + if (negative) sign = '-'; + if (*cp == 0) + cp++; + + // Calculate padding. + int fieldsize = size + fpprec; + if (sign) fieldsize++; + int padding = 0; + int w = width(0); + if (fieldsize < w) + padding = w - fieldsize; + + // Do actual output. + register streambuf* sbuf = rdbuf(); + register i; + char fill_char = fill(); + ios::fmtflags pad_kind = + flags() & (ios::left|ios::right|ios::internal); + if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust. + && pad_kind != (ios::fmtflags)ios::internal) + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); + if (sign) + sbuf->sputc(sign); + if (pad_kind == (ios::fmtflags)ios::internal) + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); + + // Emit the actual concented field, followed by extra zeros. + sbuf->sputn(cp, size); + for (i = fpprec; --i >= 0; ) sbuf->sputc('0'); + + if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); +#endif + osfx(); + } + return *this; +} + +ostream& ostream::operator<<(const char *s) +{ + if (opfx()) { + if (s == NULL) + s = "(null)"; + int len = strlen(s); + int w = width(0); + char fill_char = fill(); + register streambuf *sbuf = rdbuf(); + register int padding = w > len ? w - len : 0; + if (!(flags() & ios::left)) // Default adjustment. + while (--padding >= 0) sbuf->sputc(fill_char); + sbuf->sputn(s, len); + if (flags() & ios::left) // Left adjustment. + while (--padding >= 0) sbuf->sputc(fill_char); + osfx(); + } + return *this; +} + +ostream& ostream::operator<<(const void *p) +{ + if (opfx()) { + form("%p", p); + osfx(); + } + return *this; +} + +ostream& ostream::operator<<(register streambuf* sbuf) +{ + if (opfx()) { + register streambuf* outbuf = rdbuf(); + // FIXME: Should optimize! + for (;;) { + register int ch = sbuf->sbumpc(); + if (ch == EOF) break; + if (outbuf->sputc(ch) == EOF) { + set(ios::badbit); + break; + } + } + osfx(); + } + return *this; +} + +ostream::ostream(streambuf* sb, ostream* tied) : ios(sb, tied) +{ + _flags |= ios::dont_close; +} + +ostream& ostream::seekp(streampos pos) +{ + pos = _strbuf->seekpos(pos, ios::out); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +ostream& ostream::seekp(streamoff off, _seek_dir dir) +{ + streampos pos = _strbuf->seekoff(off, dir, ios::out); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos ostream::tellp() +{ + streampos pos = _strbuf->seekoff(0, ios::cur, ios::out); + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +ostream& ostream::form(const char *format ...) +{ + if (opfx()) { + va_list ap; + va_start(ap, format); + _strbuf->vform(format, ap); + va_end(ap); + } + return *this; +} + +ostream& ostream::vform(const char *format, _G_va_list args) +{ + if (opfx()) + _strbuf->vform(format, args); + return *this; +} + +ostream& ostream::flush() +{ + if (_strbuf->sync()) + set(ios::badbit); + return *this; +} + +ostream& flush(ostream& outs) +{ + return outs.flush(); +} + +istream& ws(istream& ins) +{ + if (ins.ipfx1()) { + int ch = skip_ws(ins._strbuf); + if (ch == EOF) + ins.set(ios::eofbit); + else + ins._strbuf->sputbackc(ch); + } + return ins; +} + +// Skip white-space. Return 0 on failure (EOF), or 1 on success. +// Differs from ws() manipulator in that failbit is set on EOF. +// Called by ipfx() and ipfx0() if needed. + +int istream::_skip_ws() +{ + int ch = skip_ws(_strbuf); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + return 0; + } + else { + _strbuf->sputbackc(ch); + return 1; + } +} + +ostream& ends(ostream& outs) +{ + outs.put('\0'); + return outs; +} + +ostream& endl(ostream& outs) +{ + return flush(outs.put('\n')); +} + +ostream& ostream::write(const char *s, int n) +{ + if (opfx()) { + if (_strbuf->sputn(s, n) != n) + set(ios::failbit); + } + return *this; +} + +void ostream::do_osfx() +{ + if (flags() & ios::unitbuf) + flush(); + if (flags() & ios::stdio) { + fflush(stdout); + fflush(stderr); + } +} + +iostream::iostream(streambuf* sb, ostream* tied) : ios(sb, tied) +{ + _flags |= ios::dont_close; + _gcount = 0; +} + +// NOTE: extension for compatibility with old libg++. +// Not really compatible with fistream::close(). +#ifdef _STREAM_COMPAT +void ios::close() +{ + if (!(_flags & (unsigned int)ios::dont_close)) + delete _strbuf; + else if (_strbuf->_flags & _S_IS_FILEBUF) + ((struct filebuf*)_strbuf)->close(); + else if (_strbuf != NULL) + _strbuf->sync(); + _flags |= ios::dont_close; + _strbuf = NULL; + _state = badbit; +} + +int istream::skip(int i) +{ + int old = (_flags & ios::skipws) != 0; + if (i) + _flags |= ios::skipws; + else + _flags &= ~ios::skipws; + return old; +} +#endif diff --git a/gnu/lib/libg++/iostream/iostream.h b/gnu/lib/libg++/iostream/iostream.h new file mode 100644 index 00000000000..d6742721524 --- /dev/null +++ b/gnu/lib/libg++/iostream/iostream.h @@ -0,0 +1,228 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: iostream.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#ifndef _IOSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#define _IOSTREAM_H + +#include <streambuf.h> + +class istream; class ostream; +typedef ios& (*__manip)(ios&); +typedef istream& (*__imanip)(istream&); +typedef ostream& (*__omanip)(ostream&); + +extern istream& ws(istream& ins); +extern ostream& flush(ostream& outs); +extern ostream& endl(ostream& outs); +extern ostream& ends(ostream& outs); + +class ostream : virtual public ios +{ + // NOTE: If fields are changed, you must fix _fake_ostream in stdstreams.C! + void do_osfx(); + public: + ostream() { } + ostream(streambuf* sb, ostream* tied=NULL); + int opfx() { + if (!good()) return 0; else { if (_tie) _tie->flush(); return 1;} } + void osfx() { if (flags() & (ios::unitbuf|ios::stdio)) + do_osfx(); } + streambuf* ostreambuf() const { return _strbuf; } + ostream& flush(); + ostream& put(char c) { _strbuf->sputc(c); return *this; } + ostream& put(unsigned char c) { return put((char)c); } + + ostream& write(const char *s, int n); + ostream& write(const unsigned char *s, int n) { return write((const char*)s, n);} +#ifndef _G_BROKEN_SIGNED_CHAR + ostream& put(signed char c) { return put((char)c); } + ostream& write(const signed char *s, int n) { return write((const char*)s, n);} +#endif + ostream& write(const void *s, int n) { return write((const char*)s, n);} + ostream& seekp(streampos); + ostream& seekp(streamoff, _seek_dir); + streampos tellp(); + ostream& form(const char *format ...); + ostream& vform(const char *format, _G_va_list args); + + ostream& operator<<(char c); + ostream& operator<<(unsigned char c) { return (*this) << (char)c; } +#ifndef _G_BROKEN_SIGNED_CHAR + ostream& operator<<(signed char c) { return (*this) << (char)c; } +#endif + ostream& operator<<(const char *s); + ostream& operator<<(const unsigned char *s) + { return (*this) << (const char*)s; } +#ifndef _G_BROKEN_SIGNED_CHAR + ostream& operator<<(const signed char *s) + { return (*this) << (const char*)s; } +#endif + ostream& operator<<(const void *p); + 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 + ostream& operator<<(short n) {return operator<<((int)n);} + ostream& operator<<(unsigned short n) {return operator<<((unsigned int)n);} + ostream& operator<<(double n); + ostream& operator<<(float n) { return operator<<((double)n); } + ostream& operator<<(__omanip func) { return (*func)(*this); } + ostream& operator<<(__manip func) {(*func)(*this); return *this;} + ostream& operator<<(streambuf*); +}; + +class istream : virtual public ios +{ + // NOTE: If fields are changed, you must fix _fake_istream in stdstreams.C! + _G_ssize_t _gcount; + + int _skip_ws(); + public: + istream() { _gcount = 0; } + istream(streambuf* sb, ostream*tied=NULL); + streambuf* istreambuf() const { return _strbuf; } + istream& get(char* ptr, int len, char delim = '\n'); + istream& get(unsigned char* ptr, int len, char delim = '\n') + { return get((char*)ptr, len, delim); } + istream& get(char& c); + istream& get(unsigned char& c) { return get((char&)c); } + istream& getline(char* ptr, int len, char delim = '\n'); + istream& getline(unsigned char* ptr, int len, char delim = '\n') + { return getline((char*)ptr, len, delim); } +#ifndef _G_BROKEN_SIGNED_CHAR + istream& get(signed char& c) { return get((char&)c); } + istream& get(signed char* ptr, int len, char delim = '\n') + { return get((char*)ptr, len, delim); } + istream& getline(signed char* ptr, int len, char delim = '\n') + { return getline((char*)ptr, len, delim); } +#endif + istream& read(char *ptr, int n); + istream& read(unsigned char *ptr, int n) { return read((char*)ptr, n); } +#ifndef _G_BROKEN_SIGNED_CHAR + istream& read(signed char *ptr, int n) { return read((char*)ptr, n); } +#endif + istream& read(void *ptr, int n) { return read((char*)ptr, n); } + istream& get(streambuf& sb, char delim = '\n'); + istream& gets(char **s, char delim = '\n'); + int ipfx(int need) { + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie && (need == 0 || rdbuf()->in_avail() < need)) _tie->flush(); + if (!need && (flags() & ios::skipws)) return _skip_ws(); + else return 1; + } + } + int ipfx0() { // Optimized version of ipfx(0). + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie) _tie->flush(); + if (flags() & ios::skipws) return _skip_ws(); + else return 1; + } + } + int ipfx1() { // Optimized version of ipfx(1). + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie && rdbuf()->in_avail() == 0) _tie->flush(); + return 1; + } + } + void isfx() { } + int get() { if (!ipfx1()) return EOF; + else { int ch = _strbuf->sbumpc(); + if (ch == EOF) set(ios::eofbit); + return ch; + } } + int peek(); + _G_ssize_t gcount() { return _gcount; } + istream& ignore(int n=1, int delim = EOF); + istream& seekg(streampos); + istream& seekg(streamoff, _seek_dir); + streampos tellg(); + istream& putback(char ch) { + if (good() && _strbuf->sputbackc(ch) == EOF) clear(ios::badbit); + return *this;} + istream& unget() { + if (good() && _strbuf->sungetc() == EOF) clear(ios::badbit); + return *this;} + istream& scan(const char *format ...); + istream& vscan(const char *format, _G_va_list args); +#ifdef _STREAM_COMPAT + istream& unget(char ch) { return putback(ch); } + int skip(int i); +#endif + + istream& operator>>(char*); + istream& operator>>(unsigned char* p) { return operator>>((char*)p); } +#ifndef _G_BROKEN_SIGNED_CHAR + istream& operator>>(signed char*p) { return operator>>((char*)p); } +#endif + istream& operator>>(char& c); + istream& operator>>(unsigned char& c) {return operator>>((char&)c);} +#ifndef _G_BROKEN_SIGNED_CHAR + istream& operator>>(signed char& c) {return operator>>((char&)c);} +#endif + istream& operator>>(int&); + istream& operator>>(long&); +#ifdef __GNUG__ + istream& operator>>(long long&); +#endif + istream& operator>>(short&); + istream& operator>>(unsigned int&); + istream& operator>>(unsigned long&); +#ifdef __GNUG__ + istream& operator>>(unsigned long long&); +#endif + istream& operator>>(unsigned short&); + istream& operator>>(float&); + istream& operator>>(double&); + istream& operator>>( __manip func) {(*func)(*this); return *this;} + istream& operator>>(__imanip func) { return (*func)(*this); } + istream& operator>>(streambuf*); +}; + + +class iostream : public istream, public ostream +{ + _G_ssize_t _gcount; + public: + iostream() { _gcount = 0; } + iostream(streambuf* sb, ostream*tied=NULL); +}; + +extern istream cin; +extern ostream cout, cerr, clog; // clog->rdbuf() == cerr->rdbuf() + +struct Iostream_init { } ; // Compatibility hack for AT&T library. + +inline ios& dec(ios& i) +{ i.setf(ios::dec, ios::dec|ios::hex|ios::oct); return i; } +inline ios& hex(ios& i) +{ i.setf(ios::hex, ios::dec|ios::hex|ios::oct); return i; } +inline ios& oct(ios& i) +{ i.setf(ios::oct, ios::dec|ios::hex|ios::oct); return i; } + +#endif /*!_IOSTREAM_H*/ diff --git a/gnu/lib/libg++/iostream/makebuf.C b/gnu/lib/libg++/iostream/makebuf.C new file mode 100644 index 00000000000..592f59ec396 --- /dev/null +++ b/gnu/lib/libg++/iostream/makebuf.C @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +// Modified for GNU iostream by Per Bothner 1991. + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include "ioprivate.h" +#include "fstream.h" +#include <sys/types.h> +#include <sys/stat.h> + +/* + * Allocate a file buffer, or switch to unbuffered I/O. + * Per the ANSI C standard, ALL tty devices default to line buffered. + * + * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek + * optimisation) right after the _fstat() that finds the buffer size. + */ +int filebuf::doallocate() +{ + register size_t size, couldbetty; + register char *p; + struct stat st; + + if (fd() < 0 || _fstat(fd(), &st) < 0) { + couldbetty = 0; + size = _G_BUFSIZ; +#if 0 + /* do not try to optimise fseek() */ + fp->_flags |= __SNPT; +#endif + } else { + couldbetty = S_ISCHR(st.st_mode); +#if _G_HAVE_ST_BLKSIZE + size = st.st_blksize <= 0 ? _G_BUFSIZ : st.st_blksize; +#else + size = _G_BUFSIZ; +#endif + } +#ifdef USE_MALLOC_BUF + if ((p = malloc(size)) == NULL) { + unbuffered(1); +// fp->_bf._base = fp->_p = fp->_nbuf; +// fp->_bf._size = 1; + return EOF; + } +#else + p = ALLOC_BUF(size); +#endif + setb(p, p+size, 1); + if (couldbetty && _isatty(fd())) + _flags |= _S_LINE_BUF; + return 1; +} diff --git a/gnu/lib/libg++/iostream/outfloat.C b/gnu/lib/libg++/iostream/outfloat.C new file mode 100644 index 00000000000..c677844b839 --- /dev/null +++ b/gnu/lib/libg++/iostream/outfloat.C @@ -0,0 +1,183 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" + +// Format floating-point number and print them. +// Return number of chars printed, or EOF on error. + +// sign_mode == '+' : print "-" or "+" +// sign_mode == ' ' : print "-" or " " +// sign_mode == '\0' : print "-' or "" + +int __outfloat(double value, streambuf *sb, char type, + int width, int precision, ios::fmtflags flags, + char sign_mode, char fill) +{ + int count = 0; +#define PUT(x) do {if (sb->sputc(x) < 0) goto error; count++;} while (0) +#define PUTN(p, n) \ + do {int _n=n; count+=_n; if (sb->sputn(p,_n) != _n) goto error;} while(0) +#define PADN(fill, n) \ + do {int _n = n; count+=_n; if (sb->padn(fill, _n) < 0) goto error;} while (0) + ios::fmtflags pad_kind = flags & (ios::left|ios::right|ios::internal); + int skip_zeroes = 0; + int show_dot = (flags & ios::showpoint) != 0; + int decpt; + int sign; + int mode; +#define EBUF_SIZE 12 +#define EBUF_END &ebuf[EBUF_SIZE] + char ebuf[EBUF_SIZE]; + char *end; + int exp = 0; + switch (type) { + case 'f': + mode = 3; + break; + case 'e': + case 'E': + exp = type; + mode = 2; + if (precision != 999) + precision++; // Add one to include digit before decimal point. + break; + case 'g': + case 'G': + exp = type == 'g' ? 'e' : 'E'; + if (precision == 0) precision = 1; + if (!(flags & ios::showpoint)) + skip_zeroes = 1; + type = 'g'; + mode = 2; + break; + } + /* Do the actual convension */ + if (precision == 999 && mode != 3) + mode = 0; + char *p = dtoa(value, mode, precision, &decpt, &sign, &end); + register int i; + int useful_digits = end-p; + char *exponent_start = EBUF_END; + if (mode == 0) + precision = useful_digits; + // Check if we need to emit an exponent. + if (mode != 3 && decpt != 9999) { + i = decpt - 1; + if ((type != 'g' && type != 'F') || i < -4 || i >= precision) { + // Print the exponent into ebuf. + // We write ebuf in reverse order (right-to-left). + char sign; + if (i >= 0) + sign = '+'; + else + sign = '-', i = -i; + /* Note: ANSI requires at least 2 exponent digits. */ + do { + *--exponent_start = (i % 10) + '0'; + i /= 10; + } while (i >= 10); + *--exponent_start = i + '0'; + *--exponent_start = sign; + *--exponent_start = exp; + } + } + int exponent_size = EBUF_END - exponent_start; + if (mode == 1) + precision = 1; + /* If we print an exponent, always show just one digit before point. */ + if (exponent_size) + decpt = 1; + if (decpt == 9999) { // Infinity or NaN + decpt = useful_digits; + precision = 0; + show_dot = 0; + } + + // dtoa truncates trailing zeroes. Set the variable trailing_zeroes to + // the number of 0's we have to add (after the decimal point). + int trailing_zeroes = 0; + if (skip_zeroes) + trailing_zeroes = 0; + else if (type == 'f') + trailing_zeroes = useful_digits <= decpt ? precision + : precision-(useful_digits-decpt); + else if (exponent_size) // 'e' 'E' or 'g' format using exponential notation. + trailing_zeroes = precision - useful_digits; + else // 'g' format not using exponential notation. + trailing_zeroes = useful_digits <= decpt ? precision - decpt + : precision-useful_digits; + if (trailing_zeroes < 0) trailing_zeroes = 0; + + if (trailing_zeroes != 0 || useful_digits > decpt) + show_dot = 1; + int print_sign; + if (sign_mode == 0) + print_sign = sign ? '-' : 0; + else if (sign_mode == '+') + print_sign = sign ? '-' : '+'; + else /* if (sign_mode == ' ') */ + print_sign = sign ? '-' : ' '; + + // Calculate the width (before padding). + int unpadded_width = + (print_sign != 0) + trailing_zeroes + exponent_size + show_dot + + useful_digits + + (decpt > useful_digits ? decpt - useful_digits + : decpt > 0 ? 0 : 1 - decpt); + + int padding = width > unpadded_width ? width - unpadded_width : 0; + if (padding > 0 + && pad_kind != (ios::fmtflags)ios::left + && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust. + PADN(fill, padding); + if (print_sign) + PUT(print_sign); + if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) + PADN(fill, padding); + if (decpt > 0) { + if (useful_digits >= decpt) + PUTN(p, decpt); + else { + PUTN(p, useful_digits); + PADN('0', decpt-useful_digits); + } + if (show_dot) { + PUT('.'); + // Print digits after the decimal point. + if (useful_digits > decpt) + PUTN(p + decpt, useful_digits-decpt); + } + } + else { + PUT('0'); + if (show_dot) { + PUT('.'); + PADN('0', -decpt); + // Print digits after the decimal point. + PUTN(p, useful_digits); + } + } + PADN('0', trailing_zeroes); + if (exponent_size) + PUTN(exponent_start, exponent_size); + if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment + PADN(fill, padding); + return count; + error: + return EOF; +} diff --git a/gnu/lib/libg++/iostream/parsestream.C b/gnu/lib/libg++/iostream/parsestream.C new file mode 100644 index 00000000000..49135da7709 --- /dev/null +++ b/gnu/lib/libg++/iostream/parsestream.C @@ -0,0 +1,307 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "ioprivate.h" +#include "parsestream.h" + +streambuf* parsebuf::setbuf(char*, int) +{ + return NULL; +} + +int parsebuf::tell_in_line() +{ + return 0; +} + +int parsebuf::pbackfail(int c) +{ + if (c == EOF) + return 0; + if (seekoff(-1, ios::cur) == EOF) + return EOF; + return (unsigned char)c; +} + +char* parsebuf::current_line() { return NULL; } + +streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int) +{ + // Make offset relative to line start. + switch (dir) { + case ios::beg: + offset -= pos_at_line_start; + break; + case ios::cur: + offset += tell_in_line(); + break; + default: + return EOF; + } + if (offset < -1) + return EOF; + if (offset > _line_length + 1) + return EOF; + return seek_in_line(offset) + pos_at_line_start; +} + +// string_parsebuf invariants: +// The reserve ares (base() .. ebuf()) is always the entire string. +// The get area (eback() .. egptr()) is the extended current line +// (i.e. with the '\n' at either end, if these exist). + +string_parsebuf::string_parsebuf(char *buf, int len, + int delete_at_close /* = 0*/) +: parsebuf() +{ + setb(buf, buf+len, delete_at_close); + register char *ptr = buf; + while (ptr < ebuf() && *ptr != '\n') ptr++; + _line_length = ptr - buf; + setg(buf, buf, ptr); +} + +int string_parsebuf::underflow() +{ + register char* ptr = egptr(); // Point to end of current_line + do { + int i = right() - ptr; + if (i <= 0) + return EOF; + ptr++; i--; // Skip '\n'. + char *line_start = ptr; + while (ptr < right() && *ptr == '\n') ptr++; + setg(line_start-1, line_start, ptr + (ptr < right())); + pos_at_line_start = line_start - left(); + _line_length = ptr - line_start; + __line_number++; + } while (gptr() == ptr); + return *gptr(); +} + +char* string_parsebuf::current_line() +{ + char *ptr = eback(); + if (__line_number > 0) + ptr++; // Skip '\n' at end of previous line. + return ptr; +} + +int string_parsebuf::tell_in_line() +{ + int offset = gptr() - eback(); + if (__line_number > 0) + offset--; + return offset; +} + +int string_parsebuf::seek_in_line(int i) +{ + int delta = i - tell_in_line(); + gbump(delta); // FIXME: Needs error (bounds) checking! + return i; +} + +static const char NewLine[1] = { '\n' }; + +general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf) + : parsebuf() +{ + delete_buf = delete_arg_buf; + sbuf = buf; + int buf_size = 128; + char* buffer = ALLOC_BUF(buf_size); + setb(buffer, buffer+buf_size, 1); +// setg(buffer, buffer, buffer); +} + +general_parsebuf::~general_parsebuf() +{ + if (delete_buf) + delete sbuf; +} + +int general_parsebuf::underflow() +{ + register char *ptr = base(); + int has_newline = eback() < gptr() && gptr()[-1] == '\n'; + if (has_newline) + *ptr++ = '\n'; + register streambuf *sb = sbuf; + register int ch; + for (;;) { + ch = sb->sbumpc(); + if (ch == EOF) + break; + if (ptr == ebuf()) { + int old_size = ebuf() - base(); + char *new_buffer = new char[old_size * 2]; + memcpy(new_buffer, base(), old_size); + setb(new_buffer, new_buffer + 2 * old_size, 1); + ptr = new_buffer + old_size; + } + *ptr++ = ch; + if (ch == '\n') + break; + } + char *cur_pos = base() + has_newline; + pos_at_line_start += _line_length + 1; + _line_length = ptr - cur_pos; + if (ch != EOF || _line_length > 0) + __line_number++; + setg(base(), cur_pos, ptr); + return ptr == cur_pos ? EOF : cur_pos[0]; +} + +char* general_parsebuf::current_line() +{ + char* ret = base(); + if (__line_number > 1) + ret++; // Move past '\n' from end of previous line. + return ret; +} + +int general_parsebuf::tell_in_line() +{ + int off = gptr() - base(); + if (__line_number > 1) + off--; // Subtract 1 for '\n' from end of previous line. + return off; +} + +int general_parsebuf::seek_in_line(int i) +{ + if (__line_number == 0) + (void)general_parsebuf::underflow(); + if (__line_number > 1) + i++; // Add 1 for '\n' from end of previous line. + if (i < 0) i = 0; + int len = egptr() - eback(); + if (i > len) i = len; + setg(base(), base() + i, egptr()); + return i; +} + +func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf() +{ + read_func = func; + arg = argm; + buf_start = NULL; + buf_end = NULL; + setb((char*)NewLine, (char*)NewLine+1, 0); + setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1); + backed_up_to_newline = 0; +} + +int func_parsebuf::tell_in_line() +{ + if (buf_start == NULL) + return 0; + if (egptr() != (char*)NewLine+1) + // Get buffer was line buffer. + return gptr() - buf_start; + if (backed_up_to_newline) + return -1; // Get buffer is '\n' preceding current line. + // Get buffer is '\n' following current line. + return (buf_end - buf_start) + (gptr() - (char*)NewLine); +} + +char* func_parsebuf::current_line() +{ + return buf_start; +} + +int func_parsebuf::seek_in_line(int i) +{ + if (i < 0) { + // Back up to preceding '\n'. + if (i < -1) i = -1; + backed_up_to_newline = 1; + setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1); + return i; + } + backed_up_to_newline = 0; + int line_length = buf_end-buf_start; + if (i <= line_length) { + setg(buf_start, buf_start+i, buf_end); + return i; + } + i -= line_length; + if (i > 0) i = 1; + setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1); + return line_length + i; +} + +int func_parsebuf::underflow() +{ + retry: + if (gptr() < egptr()) + return *gptr(); + if (gptr() != (char*)NewLine+1) { + // Get buffer was line buffer. Move to following '\n'. + setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1); + return *gptr(); + } + if (backed_up_to_newline) + // Get buffer was '\n' preceding current line. Move to current line. + backed_up_to_newline = 0; + else { + // Get buffer was '\n' following current line. Read new line. + if (buf_start) free(buf_start); + char *str = (*read_func)(arg); + buf_start = str; + if (str == NULL) + return EOF; + // Initially, _line_length == -1, so pos_at_line_start becomes 0. + pos_at_line_start += _line_length + 1; + _line_length = strlen(str); + buf_end = str + _line_length; + __line_number++; + } + setg(buf_start, buf_start, buf_end); + goto retry; +} + +#if 0 +size_t parsebuf::line_length() +{ + if (current_line_length == (size_t)(-1)) // Initial value; + (void)sgetc(); + return current_line_length; +} +#endif + +int parsebuf::seek_in_line(int i) +{ +#if 1 + abort(); + return 0; // Suppress warning. +#else + if (i > 0) { + size_t len = line_length(); + if ((unsigned)i > len) i = len; + } + else if (i < -1) i = -1; + int new_pos = seekoff(pos_at_line_start + i, ios::beg); + if (new_pos == EOF) + return tell_in_line(); + else return new_pos - pos_at_line_start; +#endif +} diff --git a/gnu/lib/libg++/iostream/parsestream.h b/gnu/lib/libg++/iostream/parsestream.h new file mode 100644 index 00000000000..95c1242928a --- /dev/null +++ b/gnu/lib/libg++/iostream/parsestream.h @@ -0,0 +1,147 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: parsestream.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#ifndef PARSESTREAM_H +#define PARSESTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include "streambuf.h" + +// A parsebuf is a streambuf optimized for scanning text files. +// It keeps track of line and column numbers. +// It is guaranteed to remember the entire current line, +// as well the '\n'-s on either side of it (if they exist). +// You can arbitrarily seek (or unget) within this extended line. +// Other backward seeks are not supported. +// Normal read semantics are supported (and hence istream operators like >>). + +class parsebuf : public backupbuf { + protected: + _G_fpos_t pos_at_line_start; + long _line_length; + unsigned long __line_number; + char *buf_start; + char *buf_end; + + public: + parsebuf *chain; + + // Return column number (raw - don't handle tabs etc). + // Retult can be -1, meaning: at '\n' before current line. + virtual int tell_in_line(); + + // seek to (raw) column I in current line. + // Result is new (raw) column position - differs from I if unable to seek. + // Seek to -1 tries to seek to before previous LF. + virtual int seek_in_line(int i); + + // Note: there is no "current line" initially, until something is read. + + // Current line number, starting with 0. + // If tell_in_line()==-1, then line number of next line. + int line_number() { return __line_number; } + + // Length of current line, not counting either '\n'. + int line_length() { return _line_length; } + // Current line - not a copy, so file ops may trash it. + virtual char* current_line(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streambuf* setbuf(char* p, int len); + protected: + parsebuf() : backupbuf() { chain= NULL; + __line_number = 0; pos_at_line_start = 0; _line_length = -1; } + virtual int pbackfail(int c); +}; + +// A string_parsebuf is a parsebuf whose source is a fixed string. + +class string_parsebuf : public parsebuf { + public: + int do_delete; + string_parsebuf(char *str, int len, int delete_at_close=0); + virtual int underflow(); + virtual char* current_line(); + virtual int seek_in_line(int i); + virtual int tell_in_line(); + char *left() const { return base(); } + char *right() const { return ebuf(); } +// streampos seekoff(streamoff, _seek_dir, int); +}; + +// A func_parsebuf calls a given function to get new input. +// Each call returns an entire NUL-terminated line (without the '\n'). +// That line has been allocated with malloc(), not new. +// The interface is tailored to the GNU readline library. +// Example: +// char* DoReadLine(void* arg) +// { +// char *line = readline((char*)arg); /* 'arg' is used as prompt. */ +// if line == NULL) { putc('\n', stderr); return NULL; } +// if (line[0] != '\0') add_history(line); +// return line; +// } +// char PromptBuffer[100] = "> "; +// func_parsebuf my_stream(DoReadLine, PromptBuffer); + +typedef char *(*CharReader)(void *arg); +class istream; + +class func_parsebuf : public parsebuf { + public: + void *arg; + CharReader read_func; + int backed_up_to_newline; + func_parsebuf(CharReader func, void *argm = NULL); + int underflow(); + virtual int tell_in_line(); + virtual int seek_in_line(int i); + virtual char* current_line(); +}; + +// A general_parsebuf is a parsebuf which gets its input from some +// other streambuf. It explicitly buffers up an entire line. + +class general_parsebuf : public parsebuf { + public: + streambuf *sbuf; + int delete_buf; // Delete sbuf when destroying this. + general_parsebuf(streambuf *buf, int delete_arg_buf = 0); + int underflow(); + virtual int tell_in_line(); + virtual int seek_in_line(int i); + ~general_parsebuf(); + virtual char* current_line(); +}; + +#if 0 +class parsestream : public istream { + streammarker marks[2]; + short _first; // of the two marks; either 0 or 1 + int _lineno; + int first() { return _first; } + int second() { return 1-_first; } + int line_length() { marks[second].delta(marks[first]); } + int line_length() { marks[second].delta(marks[first]); } + int seek_in_line(int i); + int tell_in_line(); + int line_number(); +}; +#endif +#endif /*!defined(PARSESTREAM_H)*/ diff --git a/gnu/lib/libg++/iostream/procbuf.C b/gnu/lib/libg++/iostream/procbuf.C new file mode 100644 index 00000000000..842cd3c41e2 --- /dev/null +++ b/gnu/lib/libg++/iostream/procbuf.C @@ -0,0 +1,126 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#define _POSIX_SOURCE +#include "ioprivate.h" +#include "procbuf.h" +#include <signal.h> +#include <unistd.h> +#include <sys/wait.h> + + +#ifndef FORK +#define FORK vfork +#ifndef __NetBSD__ +extern "C" _G_pid_t vfork(void); +#else +extern "C" int vfork(void); +#endif +#endif + +procbuf::procbuf(const char *command, int mode) : filebuf() +{ + open(command, mode); +} + +procbuf *procbuf::open(const char *command, int mode) +{ + int read_or_write; + if (is_open()) + return NULL; + int pipe_fds[2]; + int parent_end, child_end; + if (::pipe(pipe_fds) < 0) + return NULL; + if (mode == ios::in) { + parent_end = pipe_fds[0]; + child_end = pipe_fds[1]; + read_or_write = _S_NO_WRITES; + } + else { + parent_end = pipe_fds[1]; + child_end = pipe_fds[0]; + read_or_write = _S_NO_READS; + } + _pid = FORK(); + if (_pid == 0) { + ::close(parent_end); + int child_std_end = mode == ios::in ? 1 : 0; + if (child_end != child_std_end) { + ::dup2(child_end, child_std_end); + ::close(child_end); + } + ::execl("/bin/sh", "sh", "-c", command, NULL); + ::_exit(127); + } + ::close(child_end); + if (_pid < 0) { + ::close(parent_end); + return NULL; + } + _fb._fileno = parent_end; + xsetflags(read_or_write, _S_NO_READS|_S_NO_WRITES); + return this; +} + +/* #define USE_SIGMASK */ + +int procbuf::sys_close() +{ + _G_pid_t wait_pid; + int status = filebuf::sys_close(); + if (status < 0) + return status; + int wstatus; +#if defined(SIG_BLOCK) && defined(SIG_SETMASK) + sigset_t set, oset; + sigemptyset (&set); + sigaddset (&set, SIGINT); + sigaddset (&set, SIGQUIT); + sigaddset (&set, SIGHUP); + sigprocmask (SIG_BLOCK, &set, &oset); +#else +#ifdef USE_SIGMASK + int mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP)); +#else + typedef void (*void_func)(int); + void_func intsave = (void_func)signal(SIGINT, SIG_IGN); + void_func quitsave = (void_func)signal(SIGQUIT, SIG_IGN); + void_func hupsave = (void_func)signal(SIGHUP, SIG_IGN); +#endif +#endif + while ((wait_pid = wait(&wstatus)) != _pid && wait_pid != -1) { } +#if defined(SIG_BLOCK) && defined(SIG_SETMASK) + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); +#else +#ifdef USE_SIGMASK + (void) sigsetmask(mask); +#else + signal(SIGINT, intsave); + signal(SIGQUIT, quitsave); + signal(SIGHUP, hupsave); +#endif +#endif + if (wait_pid == -1) + return -1; + return 0; +} + +procbuf::~procbuf() +{ + close(); +} diff --git a/gnu/lib/libg++/iostream/procbuf.h b/gnu/lib/libg++/iostream/procbuf.h new file mode 100644 index 00000000000..1100fcfc792 --- /dev/null +++ b/gnu/lib/libg++/iostream/procbuf.h @@ -0,0 +1,31 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: procbuf.h,v 1.1 1995/10/18 08:38:13 deraadt Exp $ + +#include <streambuf.h> + +class procbuf : public filebuf { + _G_pid_t _pid; + public: + procbuf() : filebuf() { } + procbuf(const char *command, int mode); + procbuf* open(const char *command, int mode); + procbuf *close() { return (procbuf*)filebuf::close(); } + virtual int sys_close(); + ~procbuf(); +}; diff --git a/gnu/lib/libg++/iostream/sbufvform.C b/gnu/lib/libg++/iostream/sbufvform.C new file mode 100644 index 00000000000..533fd719d09 --- /dev/null +++ b/gnu/lib/libg++/iostream/sbufvform.C @@ -0,0 +1,856 @@ +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Actual printf innards. + * + * This code is large and complicated... + */ + +#include <sys/types.h> +#include "ioprivate.h" +#include <string.h> +#include <stdarg.h> + +/* + * Define FLOATING_POINT to get floating point. + */ +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +/* end of configuration stuff */ + + +/* + * Helper class and function for `fprintf to unbuffered': creates a + * temporary buffer. We only work on write-only files; this avoids + * worries about ungetc buffers and so forth. + */ + +class help_streambuf : public backupbuf { + public: + char *buffer; + int buf_size; + streambuf *sb; + help_streambuf(streambuf *sbuf, char *buf, int n) { + sb = sbuf; buffer = buf; buf_size = n; + setp(buffer, buffer+buf_size); } + ~help_streambuf(); + virtual int overflow(int c = EOF); +}; + +int help_streambuf::overflow(int c) +{ + int used = pptr() - pbase(); + if (used) { + sb->sputn(pbase(), used); + pbump(-used); + } + if (c == EOF || buf_size == 0) + return sb->overflow(c); + return sputc(c); +} +help_streambuf::~help_streambuf() +{ + int used = pptr() - pbase(); + if (used) { + sb->sputn(pbase(), used); + pbump(-used); + } +} + +int help_vform(streambuf *sb, char const *fmt0, va_list ap) +{ + char buf[_G_BUFSIZ]; + help_streambuf helper(sb, buf, _G_BUFSIZ); + return helper.vform(fmt0, ap); +} + +#ifdef FLOATING_POINT + +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 +extern "C" double modf(double, double*); + +#else /* no FLOATING_POINT */ + +#define BUF 40 + +#endif /* FLOATING_POINT */ + + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define LONGINT 0x01 /* long integer */ +#define LONGDBL 0x02 /* long double; unimplemented */ +#define SHORTINT 0x04 /* short integer */ +#define ALT 0x08 /* alternate form */ +#define LADJUST 0x10 /* left adjustment */ +#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */ +#define HEXPREFIX 0x40 /* add 0x or 0X prefix */ + +int streambuf::vform(char const *fmt0, _G_va_list ap) +{ + register const char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n; /* handy integer (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + const char *fmark; /* for remembering a place in fmt */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ +#ifdef FLOATING_POINT + int softsign; /* temporary negative sign for floats */ + double _double; /* double precision arguments %[eEfgG] */ +#ifndef USE_DTOA + int fpprec; /* `extra' floating precision in [eEfgG] */ +#endif +#endif + unsigned long _ulong; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int dpad; /* extra 0 padding needed for integers */ + int fieldsz; /* field size expanded by sign, dpad etc */ + // The initialization of 'size' is to suppress a warning that + // 'size' might be used unitialized. It seems gcc can't + // quite grok this spaghetti code ... + int size = 0; /* size of converted field or string */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + + /* + * Choose PADSIZE to trade efficiency vs size. If larger + * printf fields occur frequently, increase PADSIZE (and make + * the initialisers below longer). + */ +#define PADSIZE 16 /* pad chunk size */ + static char const blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static char const zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) \ + do { if (sputn(ptr, len) != len) goto error; } while (0) +#if 1 +#define PAD_SP(howmany) if (padn(' ', howmany) < 0) goto error; +#define PAD_0(howmany) if (padn('0', howmany) < 0) goto error; +#else +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT(with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT(with, n); \ + } \ +} +#define PAD_SP(howmany) PAD(howmany, blanks) +#define PAD_0(howmany) PAD(howmany, zeroes) +#endif + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&LONGINT ? va_arg(ap, unsigned long) : \ + flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ + (unsigned long)va_arg(ap, unsigned int)) + + /* optimise cerr (and other unbuffered Unix files) */ + if (unbuffered()) + return help_vform(this, fmt0, ap); + + fmt = fmt0; + ret = 0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) + /* void */; + if ((n = fmt - fmark) != 0) { + PRINT(fmark, n); + ret += n; + } + if (ch == '\0') + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; +#if defined(FLOATING_POINT) && !defined (USE_DTOA) + fpprec = 0; +#endif + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + flags &= ~ZEROPAD; /* '-' disables '0' */ + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + if (!(flags & LADJUST)) + flags |= ZEROPAD; /* '-' disables '0' */ + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 'c': + *(cp = buf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _ulong = SARG(); + if ((long)_ulong < 0) { + _ulong = -_ulong; + sign = '-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + _double = va_arg(ap, double); +#ifdef USE_DTOA + { + ios::fmtflags fmt_flags = 0; + int fill = ' '; + if (flags & ALT) + fmt_flags |= ios::showpoint; + if (flags & LADJUST) + fmt_flags |= ios::left; + else if (flags & ZEROPAD) + fmt_flags |= ios::internal, fill = '0'; + n = __outfloat(_double, this, ch, width, + prec < 0 ? DEFPREC : prec, + fmt_flags, sign, fill); + if (n < 0) + goto error; + ret += n; + } + // CHECK ERROR! + continue; +#else + /* + * don't do unrealistic precision; just pad it with + * zeroes later, so buffer size stays rational. + */ + if (prec > MAXFRACT) { + if ((ch != 'g' && ch != 'G') || (flags&ALT)) + fpprec = prec - MAXFRACT; + prec = MAXFRACT; + } else if (prec == -1) + prec = DEFPREC; + // __cvt_double may have to round up before the + // "start" of its buffer, i.e. + // ``intf("%.2f", (double)9.999);''; + // if the first character is still NUL, it did. + // softsign avoids negative 0 if _double < 0 but + // no significant digits will be shown. + cp = buf; + *cp = '\0'; + size = __cvt_double(_double, prec, flags, &softsign, + ch, cp, buf + sizeof(buf)); + if (softsign) + sign = '-'; + if (*cp == '\0') + cp++; + break; +#endif +#endif /* FLOATING_POINT */ + case 'n': + if (flags & LONGINT) + *va_arg(ap, long *) = ret; + else if (flags & SHORTINT) + *va_arg(ap, short *) = ret; + else + *va_arg(ap, int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _ulong = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _ulong = (unsigned long)va_arg(ap, void *); + base = HEX; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = (char*)memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _ulong = UARG(); + base = DEC; + goto nosign; + case 'X': + case 'x': + _ulong = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _ulong != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_ulong != 0 || prec != 0) { + char *xdigs; /* digits for [xX] conversion */ + /* + * unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_ulong & 7); + _ulong >>= 3; + } while (_ulong); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_ulong >= 10) { + *--cp = to_char(_ulong % 10); + _ulong /= 10; + } + *--cp = to_char(_ulong); + break; + + case HEX: + if (ch == 'X') + xdigs = "0123456789ABCDEF"; + else /* ch == 'x' || ch == 'p' */ + xdigs = "0123456789abcdef"; + do { + *--cp = xdigs[_ulong & 15]; + _ulong >>= 4; + } while (_ulong); + break; + + default: + cp = "bug in vform: bad base"; + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, + * `cp' points to a string which (if not flags&LADJUST) + * should be padded out to `width' places. If + * flags&ZEROPAD, it should first be prefixed by any + * sign or other prefix; otherwise, it should be blank + * padded before the prefix is emitted. After any + * left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print + * the string proper, then emit zeroes required by any + * leftover floating precision; finally, if LADJUST, + * pad with blanks. + */ + + /* + * compute actual size, so we know how much to pad. + */ +#if defined(FLOATING_POINT) && !defined (USE_DTOA) + fieldsz = size + fpprec; +#else + fieldsz = size; +#endif + dpad = dprec - size; + if (dpad < 0) + dpad = 0; + + if (sign) + fieldsz++; + else if (flags & HEXPREFIX) + fieldsz += 2; + fieldsz += dpad; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD_SP(width - fieldsz); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD_0(width - fieldsz); + + /* leading zeroes from decimal precision */ + PAD_0(dpad); + + /* the string or number proper */ + PRINT(cp, size); + +#if defined(FLOATING_POINT) && !defined (USE_DTOA) + /* trailing f.p. zeroes */ + PAD_0(fpprec); +#endif + + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD_SP(width - fieldsz); + + /* finally, adjust ret */ + ret += width > fieldsz ? width : fieldsz; + + } +done: + return ret; +error: + return EOF; + /* NOTREACHED */ +} + +#if defined(FLOATING_POINT) && !defined(USE_DTOA) + +static char *exponent(register char *p, register int exp, int fmtch) +{ + register char *t; + char expbuf[MAXEXP]; + + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } + else + *p++ = '+'; + t = expbuf + MAXEXP; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else { + *p++ = '0'; + *p++ = to_char(exp); + } + return (p); +} + +static char * round(double fract, int *exp, + register char *start, register char *end, + char ch, int *signp) +{ + double tmp; + + if (fract) + (void)modf(fract * 10, &tmp); + else + tmp = to_digit(ch); + if (tmp > 4) + for (;; --end) { + if (*end == '.') + --end; + if (++*end <= '9') + break; + *end = '0'; + if (end == start) { + if (exp) { /* e/E; increment exponent */ + *end = '1'; + ++*exp; + } + else { /* f; add extra digit */ + *--end = '1'; + --start; + } + break; + } + } + /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ + else if (*signp == '-') + for (;; --end) { + if (*end == '.') + --end; + if (*end != '0') + break; + if (end == start) + *signp = 0; + } + return (start); +} + +int __cvt_double(double number, register int prec, int flags, int *signp, + int fmtch, char *startp, char *endp) +{ + register char *p, *t; + register double fract; + int dotrim = 0, expcnt, gformat = 0; + double integer, tmp; + + expcnt = 0; + if (number < 0) { + number = -number; + *signp = '-'; + } else + *signp = 0; + + fract = modf(number, &integer); + + /* get an extra slot for rounding. */ + t = ++startp; + + /* + * get integer portion of number; put into the end of the buffer; the + * .01 is added for modf(356.0 / 10, &integer) returning .59999999... + */ + for (p = endp - 1; integer; ++expcnt) { + tmp = modf(integer / 10, &integer); + *p-- = to_char((int)((tmp + .01) * 10)); + } + switch (fmtch) { + case 'f': + case 'F': + /* reverse integer into beginning of buffer */ + if (expcnt) + for (; ++p < endp; *t++ = *p); + else + *t++ = '0'; + /* + * if precision required or alternate flag set, add in a + * decimal point. + */ + if (prec || flags&ALT) + *t++ = '.'; + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while (--prec && fract); + if (fract) + startp = round(fract, (int *)NULL, startp, + t - 1, (char)0, signp); + } + for (; prec--; *t++ = '0'); + break; + case 'e': + case 'E': +eformat: if (expcnt) { + *t++ = *++p; + if (prec || flags&ALT) + *t++ = '.'; + /* if requires more precision and some integer left */ + for (; prec && ++p < endp; --prec) + *t++ = *p; + /* + * if done precision and more of the integer component, + * round using it; adjust fract so we don't re-round + * later. + */ + if (!prec && ++p < endp) { + fract = 0; + startp = round((double)0, &expcnt, startp, + t - 1, *p, signp); + } + /* adjust expcnt for digit in front of decimal */ + --expcnt; + } + /* until first fractional digit, decrement exponent */ + else if (fract) { + /* adjust expcnt for digit in front of decimal */ + for (expcnt = -1;; --expcnt) { + fract = modf(fract * 10, &tmp); + if (tmp) + break; + } + *t++ = to_char((int)tmp); + if (prec || flags&ALT) + *t++ = '.'; + } + else { + *t++ = '0'; + if (prec || flags&ALT) + *t++ = '.'; + } + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while (--prec && fract); + if (fract) + startp = round(fract, &expcnt, startp, + t - 1, (char)0, signp); + } + /* if requires more precision */ + for (; prec--; *t++ = '0'); + + /* unless alternate flag, trim any g/G format trailing 0's */ + if (gformat && !(flags&ALT)) { + while (t > startp && *--t == '0'); + if (*t == '.') + --t; + ++t; + } + t = exponent(t, expcnt, fmtch); + break; + case 'g': + case 'G': + /* a precision of 0 is treated as a precision of 1. */ + if (!prec) + ++prec; + /* + * ``The style used depends on the value converted; style e + * will be used only if the exponent resulting from the + * conversion is less than -4 or greater than the precision.'' + * -- ANSI X3J11 + */ + if (expcnt > prec || (!expcnt && fract && fract < .0001)) { + /* + * g/G format counts "significant digits, not digits of + * precision; for the e/E format, this just causes an + * off-by-one problem, i.e. g/G considers the digit + * before the decimal point significant and e/E doesn't + * count it as precision. + */ + --prec; + fmtch -= 2; /* G->E, g->e */ + gformat = 1; + goto eformat; + } + /* + * reverse integer into beginning of buffer, + * note, decrement precision + */ + if (expcnt) + for (; ++p < endp; *t++ = *p, --prec); + else + *t++ = '0'; + /* + * if precision required or alternate flag set, add in a + * decimal point. If no digits yet, add in leading 0. + */ + if (prec || flags&ALT) { + dotrim = 1; + *t++ = '.'; + } + else + dotrim = 0; + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) { + /* If no integer part, don't count initial + * zeros as significant digits. */ + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while(!tmp && !expcnt); + while (--prec && fract) { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } + } + if (fract) + startp = round(fract, (int *)NULL, startp, + t - 1, (char)0, signp); + } + /* alternate format, adds 0's for precision, else trim 0's */ + if (flags&ALT) + for (; prec--; *t++ = '0'); + else if (dotrim) { + while (t > startp && *--t == '0'); + if (*t != '.') + ++t; + } + } + return (t - startp); +} + +#endif /* defined(FLOATING_POINT) && !defined(USE_DTOA) */ + +int streambuf::form(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = vform(format, ap); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/iostream/sbufvscan.C b/gnu/lib/libg++/iostream/sbufvscan.C new file mode 100644 index 00000000000..3c7d29a8c78 --- /dev/null +++ b/gnu/lib/libg++/iostream/sbufvscan.C @@ -0,0 +1,746 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +// Extensively hacked for GNU iostream by Per Bothner 1991, 1992. +// Changes copyright Per Bothner 1992. + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <ioprivate.h> +#include <ctype.h> +#ifndef NO_STDARG +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +#ifdef FLOATING_POINT +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ +#else +#define BUF 40 +#endif + +/* + * Flags used during conversion. + */ +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L: long double; unimplemented */ +#define SHORT 0x04 /* h: short */ +#define SUPPRESS 0x08 /* suppress assignment */ +#define POINTER 0x10 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x20 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ +#define SIGNOK 0x40 /* +/- is (still) legal */ +#define NDIGITS 0x80 /* no digits detected */ + +#define DPTOK 0x100 /* (float) decimal point is still legal */ +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x100 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x200 /* no zero digits detected */ + +/* + * Conversion types. + */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtol or strtoul */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +#define u_char unsigned char +#define u_long unsigned long + +extern "C" u_long strtoul(const char*, char**, int); +static const u_char *__sccl(register char *tab, register const u_char *fmt); + +// If state is non-NULL, set failbit and/or eofbit as appropriate. + +int streambuf::vscan(char const *fmt0, + _G_va_list ap, + ios *stream /* = NULL */) +{ + register const u_char *fmt = (const u_char *)fmt0; + register int c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + // Assignments to base and ccfn are just to suppress warnings from gcc. + int base = 0; /* base argument to strtol/strtoul */ + typedef u_long (*strtoulfn)(const char*, char**, int); + strtoulfn ccfn = 0; + // conversion function (strtol/strtoul) + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + int seen_eof = 0; + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + nassigned = 0; + nread = 0; + for (;;) { + c = *fmt++; + if (c == 0) + goto done; + if (isspace(c)) { + for (;;) { + c = sbumpc(); + if (c == EOF) + goto eof_failure; + if (!isspace(c)) { + sputbackc(c); + break; + } + nread++; + } + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + /* + * switch on the format. continue if done; + * break once format type is derived. + */ +again: c = *fmt++; + switch (c) { + case '%': +literal: + n = sbumpc(); + if (n == EOF) + goto eof_failure; + if (n != c) { + sputbackc(n); + goto match_failure; + } + nread++; + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'l': + flags |= LONG; + goto again; + case 'L': + flags |= LONGDBL; + goto again; + case 'h': + flags |= SHORT; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. + * Those marked `compat' are for 4.[123]BSD compatibility. + * + * (According to ANSI, E and X formats are supposed + * to the same as e and x. Sorry about that.) + */ + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = strtoul; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = strtoul; + base = 10; + break; + + case 'X': + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + +#ifdef FLOATING_POINT + case 'E': case 'F': + case 'e': case 'f': case 'g': + c = CT_FLOAT; + break; +#endif + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = __sccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *va_arg(ap, short *) = nread; + else if (flags & LONG) + *va_arg(ap, long *) = nread; + else + *va_arg(ap, int *) = nread; + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case '\0': /* compat */ + nassigned = EOF; + goto done; + + default: /* compat */ + if (isupper(c)) + flags |= LONG; + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 10; + break; + } + + /* + * We have a conversion that requires input. + */ + if (sgetc() == EOF) + goto eof_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + n = (unsigned char)*_gptr; + while (isspace(n)) { + _gptr++; + nread++; + n = sgetc(); + if (n == EOF) + goto eof_failure; + } + // Note that there is at least one character in + // the buffer, so conversions that do not set NOSKIP + // can no longer result in an input failure. + } + + /* + * Do the conversion. + */ + switch (c) { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) // FIXME! + width = 1; + if (flags & SUPPRESS) { + size_t sum = 0; + for (;;) { + if ((n = _egptr - _gptr) < (int)width) { + sum += n; + width -= n; + _gptr += n; + if (underflow() == EOF) + if (sum == 0) + goto eof_failure; + else { + seen_eof++; + break; + } + } else { + sum += width; + _gptr += width; + break; + } + } + nread += sum; + } else { + size_t r = sgetn((char*)va_arg(ap, char*), + width); + if (r != width) + goto eof_failure; + nread += r; + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = ~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) { + n = 0; + while (ccltab[(unsigned char)*_gptr]) { + n++, _gptr++; + if (--width == 0) + break; + if (sgetc() == EOF) { + if (n == 0) + goto eof_failure; + seen_eof++; + break; + } + } + if (n == 0) + goto match_failure; + } else { + p0 = p = va_arg(ap, char *); + while (ccltab[(unsigned char)*_gptr]) { + *p++ = *_gptr++; + if (--width == 0) + break; + if (sgetc() == EOF) { + if (p == p0) + goto eof_failure; + seen_eof++; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = ~0; + if (flags & SUPPRESS) { + n = 0; + while (!isspace((unsigned char)*_gptr)) { + n++, _gptr++; + if (--width == 0) + break; + if (sgetc() == EOF) { + seen_eof++; + break; + } + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace((unsigned char)*_gptr)) { + *p++ = *_gptr++; + if (--width == 0) + break; + if (sgetc() == EOF) { + seen_eof++; + break; + } + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtol/strtoul */ + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) { + c = (unsigned char)*_gptr; + /* + * Switch on the character; `goto ok' + * if we accept it as a part of number. + */ + switch (c) { + + /* + * The digit 0 is always legal, but is + * special. For %i conversions, if no + * digits (zero or nonzero) have been + * scanned (only signs), we will have + * base==0. In that case, we should set + * it to 8 and enable 0x prefixing. + * Also, if we have not scanned zero digits + * before this, do not turn off prefixing + * (someone else will turn it off if we + * have scanned any nonzero digits). + */ + case '0': + if (base == 0) { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + _gptr++; + if (sgetc() == EOF) { + seen_eof++; + break; /* EOF */ + } + } + /* + * If we had only a sign, it is no good; push + * back the sign. If the number ends in `x', + * it was [sign] '0' 'x', so push back the x + * and treat it as [sign] '0'. + */ + if (flags & NDIGITS) { + if (p > buf) + (void) sputbackc(*(u_char *)--p); + goto match_failure; + } + c = ((u_char *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + (void) sputbackc(c); + } + if ((flags & SUPPRESS) == 0) { + u_long res; + + *p = 0; + res = (*ccfn)(buf, (char **)NULL, base); + if (flags & POINTER) + *va_arg(ap, void **) = (void *)res; + else if (flags & SHORT) + *va_arg(ap, short *) = res; + else if (flags & LONG) + *va_arg(ap, long *) = res; + else + *va_arg(ap, int *) = res; + nassigned++; + } + nread += p - buf; + break; + +#ifdef FLOATING_POINT + case CT_FLOAT: + /* scan a floating point number as if by strtod */ + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + for (p = buf; width; width--) { + c = (unsigned char)*_gptr; + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) { + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) { + flags &= ~(SIGNOK | DPTOK); + goto fok; + } + break; + case 'e': case 'E': + /* no exponent without some digits */ + if ((flags&(NDIGITS|EXPOK)) == EXPOK) { + flags = + (flags & ~(EXPOK|DPTOK)) | + SIGNOK | NDIGITS; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + _gptr++; + if (sgetc() == EOF) { + seen_eof++; + break; /* EOF */ + } + } + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) { + if (flags & EXPOK) { + /* no digits at all */ + while (p > buf) + sputbackc(*(u_char *)--p); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)--p; + if (c != 'e' && c != 'E') { + (void)sputbackc(c);/* sign */ + c = *(u_char *)--p; + } + (void) sputbackc(c); + } + if ((flags & SUPPRESS) == 0) { + double res; + *p = 0; +#ifdef USE_DTOA + res = strtod(buf, NULL); +#else + res = atof(buf); +#endif + if (flags & LONG) + *va_arg(ap, double *) = res; + else + *va_arg(ap, float *) = res; + nassigned++; + } + nread += p - buf; + break; +#endif /* FLOATING_POINT */ + } + } +eof_failure: + seen_eof++; +input_failure: + if (nassigned == 0) + nassigned = -1; +match_failure: + if (stream) + stream->set(ios::failbit); +done: + if (stream && seen_eof) + stream->set(ios::eofbit); + return (nassigned); +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ +static const u_char *__sccl(register char *tab, register const u_char *fmt) +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } else + v = 0; /* default => reject */ + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return (fmt - 1);/* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset + * to the opposite of the above. + * + * The first character may be ']' (or '-') without being special; + * the last character may be '-'. + */ + v = 1 - v; + for (;;) { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) { + + case 0: /* format ended too soon */ + return (fmt - 1); + + case '-': + /* + * A scanset of the form + * [01+-] + * is defined as `the digit 0, the digit 1, + * the character +, the character -', but + * the effect of a scanset such as + * [a-zA-Z0-9] + * is implementation defined. The V7 Unix + * scanf treats `a-z' as `the letters a through + * z', but treats `a-a' as `the letter a, the + * character -, and the letter a'. + * + * For compatibility, the `-' is not considerd + * to define a range if the character following + * it is either a close bracket (required by ANSI) + * or is not numerically greater than the character + * we just stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do { /* fill in the range */ + tab[++c] = v; + } while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats + * such as [a-c-e] as `the letters a through e'. + * This too is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return (fmt - 1); + if (c == ']') + return (fmt); +#endif + break; + + case ']': /* end of scanset */ + return (fmt); + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} + +int streambuf::scan(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = vscan(format, ap); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/iostream/sgetline.C b/gnu/lib/libg++/iostream/sgetline.C new file mode 100644 index 00000000000..04745969223 --- /dev/null +++ b/gnu/lib/libg++/iostream/sgetline.C @@ -0,0 +1,64 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" + +// Algorithm based on that used by Berkeley pre-4.4 fgets implementation. + +// Read chars into buf (of size n), until delim is seen. +// Return number of chars read (at most n-1). +// If extract_delim < 0, leave delimiter unread. +// If extract_delim > 0, insert delim in output. + +long streambuf::sgetline(char* buf, size_t n, char delim, int extract_delim) +{ + register char *ptr = buf; + if (n <= 0) + return EOF; + n--; // Leave space for final '\0'. + do { + int len = egptr() - gptr(); + if (len <= 0) + if (underflow() == EOF) + break; + else + len = egptr() - gptr(); + if (len >= (int)n) + len = n; + char *t = (char*)memchr((void*)_gptr, delim, len); + if (t != NULL) { + size_t old_len = ptr-buf; + len = t - _gptr; + if (extract_delim >= 0) { + t++; + old_len++; + if (extract_delim > 0) + len++; + } + memcpy((void*)ptr, (void*)_gptr, len); + ptr[len] = 0; + _gptr = t; + return old_len + len; + } + memcpy((void*)ptr, (void*)_gptr, len); + _gptr += len; + ptr += len; + n -= len; + } while (n != 0); + *ptr = 0; + return ptr - buf; +} diff --git a/gnu/lib/libg++/iostream/stdiostream.C b/gnu/lib/libg++/iostream/stdiostream.C new file mode 100644 index 00000000000..960a9a4a60f --- /dev/null +++ b/gnu/lib/libg++/iostream/stdiostream.C @@ -0,0 +1,112 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <stdiostream.h> + +// A stdiobuf is "tied" to a FILE object (as used by the stdio package). +// Thus a stdiobuf is always synchronized with the corresponding FILE, +// though at the cost of some overhead. (If you use the implementation +// of stdio supplied with this library, you don't need stdiobufs.) +// This implementation inherits from filebuf, but implement the virtual +// functions sys_read/..., using the stdio functions fread/... instead +// of the low-level read/... system calls. This has the advantage that +// we get all of the nice filebuf semantics automatically, though +// with some overhead. + + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +stdiobuf::stdiobuf(FILE *f) : filebuf(fileno(f)) +{ + _file = f; + // Turn off buffer in stdiobuf. Instead, rely on buffering in (FILE). + // Thus the stdiobuf will be synchronized with the FILE. + setbuf(NULL, 0); +} + +_G_ssize_t stdiobuf::sys_read(char* buf, size_t size) +{ + return fread(buf, 1, size, _file); +} + +_G_ssize_t stdiobuf::sys_write(const void *buf, long n) +{ + _G_ssize_t count = fwrite(buf, 1, n, _file); + if (_fb._offset >= 0) + _fb._offset += n; + return count; +} + +_G_fpos_t stdiobuf::sys_seek(_G_fpos_t offset, _seek_dir dir) +{ + // Normally, equivalent to: fdir=dir + int fdir = + (dir == ios::beg) ? SEEK_SET : + (dir == ios::cur) ? SEEK_CUR : + (dir == ios::end) ? SEEK_END : + dir; + return fseek(_file, offset, fdir); +} + +int stdiobuf::sys_close() +{ + int status = fclose(_file); + _file = NULL; + return status; +} + +int stdiobuf::sync() +{ + if (filebuf::sync() == EOF) + return EOF; + if (!(xflags() & _S_NO_WRITES)) + if (fflush(_file)) + return EOF; +#if 0 + // This loses when writing to a pipe. + if (fseek(_file, 0, SEEK_CUR) == EOF) + return EOF; +#endif + return 0; +} + +int stdiobuf::overflow(int c /* = EOF*/) +{ + if (filebuf::overflow(c) == EOF) + return EOF; + if (c != EOF) + return c; + return fflush(_file); +} + +int stdiobuf::xsputn(const char* s, int n) +{ + // The filebuf implementation of sputn loses. + return streambuf::xsputn(s, n); +} diff --git a/gnu/lib/libg++/iostream/stdiostream.h b/gnu/lib/libg++/iostream/stdiostream.h new file mode 100644 index 00000000000..9e397b7eed9 --- /dev/null +++ b/gnu/lib/libg++/iostream/stdiostream.h @@ -0,0 +1,45 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: stdiostream.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ + +#ifndef _STDIOSTREAM_H +#define _STDIOSTREAM_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include <streambuf.h> +#include <stdio.h> + +class stdiobuf : public filebuf { + protected: + FILE *_file; + public: + FILE* stdiofile() const { return _file; } + stdiobuf(FILE *f); + virtual _G_ssize_t sys_read(char* buf, _G_size_t size); + virtual _G_fpos_t sys_seek(_G_fpos_t, _seek_dir); + virtual _G_ssize_t sys_write(const void*, long); + virtual int sys_close(); + virtual int sync(); + virtual int overflow(int c = EOF); + virtual int xsputn(const char* s, int n); +}; + +#endif /* !_STDIOSTREAM_H */ diff --git a/gnu/lib/libg++/iostream/stdstrbufs.C b/gnu/lib/libg++/iostream/stdstrbufs.C new file mode 100644 index 00000000000..2ae80fa9c41 --- /dev/null +++ b/gnu/lib/libg++/iostream/stdstrbufs.C @@ -0,0 +1,113 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" +#include <stdio.h> + +// This file defines the standard streambufs, corresponding to cin, cout, cerr. +// We define two sets: +// +// __std_filebuf_0, __std_filebuf_1, __std_filebuf_2 are filebufs using +// file descriptor 0/1/2. +// +// __stdin_stdiobuf, __stdout_stdiobuf, __stderr_stdiobuf are stdiostreams +// pointing to stdin, stdout, stderr. + + +// To avoid problems depending on constructor order (and for +// efficiency) the standard streambufs (and streams) are +// constructed statically using C-style '{ ... }' initializers. +// Since you're not allowed to do this for structs that +// have virtuals, we define fake streambuf and stream classes +// that don't have any C++-isms, and initialize those. +// To initialize the vtable field of the standard filebufs, +// we use the expression 'vt_filebuf' which must evaluate to +// (the address of) the virtual function table for the +// filebuf class. + +#if _G_NAMES_HAVE_UNDERSCORE +#define UNDERSCORE "_" +#else +#define UNDERSCORE "" +#endif + +// First define the filebuf-based objects. + +#if !defined(vt_filebuf) +#ifndef __GNUG__ +// This works for cfront. +#define vt_filebuf __vtbl__7filebuf +extern char vt_filebuf[1]; +#elif _G_DOLLAR_IN_LABEL +extern char vt_filebuf[1] asm(UNDERSCORE "_vt$filebuf"); +#else +extern char vt_filebuf[1] asm(UNDERSCORE "_vt.filebuf"); +#endif +#endif /* !defined(vt_filebuf) */ + +struct _fake_filebuf { + struct __streambuf s; + char* vtable; + struct __file_fields f; +}; + +#define FILEBUF_LITERAL(CHAIN, FLAGS) \ + { _IO_MAGIC+_S_LINKED+_S_IS_FILEBUF+_S_IS_BACKUPBUF+FLAGS, \ + 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, 0, 0, 0, 0, 0} + +#define DEF_FILEBUF(NAME, FD, CHAIN, FLAGS) \ + _fake_filebuf NAME = {FILEBUF_LITERAL(CHAIN, FLAGS), vt_filebuf, {FD}}; + +DEF_FILEBUF(__std_filebuf_0, 0, 0, _S_NO_WRITES); +DEF_FILEBUF(__std_filebuf_1, 1, (streambuf*)&__std_filebuf_0, _S_NO_READS); +DEF_FILEBUF(__std_filebuf_2, 2, (streambuf*)&__std_filebuf_1, + _S_NO_READS+_S_UNBUFFERED); + +// Nest define the stdiobuf-bases objects. + +#if !defined(vt_stdiobuf) +#ifndef __GNUG__ +// This works for cfront. +#define vt_stdiobuf __vtbl__8stdiobuf +extern char vt_stdiobuf[1]; +#elif _G_DOLLAR_IN_LABEL +extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt$stdiobuf"); +#else +extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt.stdiobuf"); +#endif +#endif /* !defined(vt_stdiobuf) */ + +struct _fake_stdiobuf { + struct __streambuf s; + char* vtable; + struct __file_fields f; + FILE *_f; +}; + +#define DEF_STDIOBUF(NAME, FILE, FD, CHAIN, FLAGS) \ + _fake_stdiobuf NAME[1] = {{ \ + FILEBUF_LITERAL(CHAIN, (FLAGS)|_S_UNBUFFERED),\ + vt_stdiobuf, {FD}, FILE}}; + +DEF_STDIOBUF(__stdin_stdiobuf, stdin, 0, (streambuf*)&__std_filebuf_2, + _S_NO_WRITES); +DEF_STDIOBUF(__stdout_stdiobuf, stdout, 1, (streambuf*)__stdin_stdiobuf, + _S_NO_READS); +DEF_STDIOBUF(__stderr_stdiobuf, stderr, 2, (streambuf*)__stdout_stdiobuf, + _S_NO_READS); + +streambuf* streambuf::_list_all = (streambuf*)__stderr_stdiobuf; diff --git a/gnu/lib/libg++/iostream/stdstreams.C b/gnu/lib/libg++/iostream/stdstreams.C new file mode 100644 index 00000000000..991371a1077 --- /dev/null +++ b/gnu/lib/libg++/iostream/stdstreams.C @@ -0,0 +1,145 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include "ioprivate.h" + +// The ANSI draft requires that operations on cin/cout/cerr can be +// mixed with operations on stdin/stdout/stderr on a character by +// character basis. This normally requires that the streambuf's +// used by cin/cout/cerr be stdiostreams. However, if the stdio +// implementation is the one that is built using this library, +// then we don't need to, since in that case stdin/stdout/stderr +// are identical to &__std_filebuf_0/&__std_filebuf_1/&__std_filebuf_2. + +#ifdef _STDIO_USES_IOSTREAM +#define USE_FILEBUF +#endif + +#ifdef NAMES_HAVE_UNDERSCORE +#define UNDERSCORE "_" +#else +#define UNDERSCORE "" +#endif + +#ifdef USE_FILEBUF +#define CIN_SBUF __std_filebuf_0 +#define COUT_SBUF __std_filebuf_1 +#define CERR_SBUF __std_filebuf_2 +static int use_stdiobuf = 0; +#else +#define CIN_SBUF __stdin_stdiobuf +#define COUT_SBUF __stdout_stdiobuf +#define CERR_SBUF __stderr_stdiobuf +static int use_stdiobuf = 1; +#endif + +struct _fake_filebuf; +extern _fake_filebuf __std_filebuf_0, __std_filebuf_1, __std_filebuf_2; +struct _fake_stdiobuf; +extern _fake_stdiobuf __stdin_stdiobuf, __stdout_stdiobuf, __stderr_stdiobuf; + +#define cin CIN +#define cout COUT +#define cerr CERR +#define clog CLOG +#include "iostream.h" +#undef cin +#undef cout +#undef cerr +#undef clog + +#ifdef __GNUC__ +#define PAD 0 /* g++ allows 0-length arrays. */ +#else +#define PAD 1 +#endif +struct _fake_istream { + struct myfields { +#ifdef __GNUC__ + _ios_fields *vb; /* pointer to virtual base class ios */ + _G_ssize_t _gcount; +#else + /* This is supposedly correct for cfront. */ + _G_ssize_t _gcount; + void *vptr; + _ios_fields *vb; /* pointer to virtual base class ios */ +#endif + } mine; + _ios_fields base; + char filler[sizeof(struct istream)-sizeof(struct _ios_fields)+PAD]; +}; +struct _fake_ostream { + struct myfields { +#ifndef __GNUC__ + void *vptr; +#endif + _ios_fields *vb; /* pointer to virtual base class ios */ + } mine; + _ios_fields base; + char filler[sizeof(struct ostream)-sizeof(struct _ios_fields)+PAD]; +}; + +#define STD_STR(SBUF, TIE, EXTRA_FLAGS) \ + (streambuf*)&SBUF, TIE, 0, ios::dont_close|ios::skipws|EXTRA_FLAGS, ' ',0,0,6 + +#ifdef __GNUC__ +#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \ + TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \ + TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#else +#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \ + TYPE NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \ + TYPE NAME = { {0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#endif + +OSTREAM_DEF(_fake_ostream, cout, COUT_SBUF, NULL, 0) +OSTREAM_DEF(_fake_ostream, cerr, CERR_SBUF, (ostream*)&cout, ios::unitbuf) +ISTREAM_DEF(_fake_istream, cin, CIN_SBUF, (ostream*)&cout, 0) + +/* Only for (partial) compatibility with AT&T's library. */ +OSTREAM_DEF(_fake_ostream, clog, CERR_SBUF, (ostream*)&cout, 0) + +// Switches between using __std_filebuf_{0,1,2} and +// __std{in,out,err}_stdiobuf for standard streams. This is +// normally not needed, but is provided for AT&T compatibility. + +int ios::sync_with_stdio(int new_state) +{ +#ifdef _STDIO_USES_IOSTREAM + // It is always synced. + return 0; +#else + if (new_state == use_stdiobuf) // The usual case now. + return use_stdiobuf; + if (new_state) { + cout.base._strbuf = (streambuf*)&__stdout_stdiobuf; + cin.base._strbuf = (streambuf*)&__stdin_stdiobuf; + cerr.base._strbuf = (streambuf*)&__stderr_stdiobuf; + clog.base._strbuf = (streambuf*)&__stderr_stdiobuf; + } else { + cout.base._strbuf = (streambuf*)&__std_filebuf_1; + cin.base._strbuf = (streambuf*)&__std_filebuf_0; + cerr.base._strbuf = (streambuf*)&__std_filebuf_2; + clog.base._strbuf = (streambuf*)&__std_filebuf_2; + } + int old_state = use_stdiobuf; + use_stdiobuf = new_state; + return old_state; +#endif +} diff --git a/gnu/lib/libg++/iostream/stream.C b/gnu/lib/libg++/iostream/stream.C new file mode 100644 index 00000000000..5ee6bbeb5a5 --- /dev/null +++ b/gnu/lib/libg++/iostream/stream.C @@ -0,0 +1,120 @@ +#include <stdarg.h> +#include "ioprivate.h" +#include "stream.h" +#include "strstream.h" + +static char Buffer[_G_BUFSIZ]; +#define EndBuffer (Buffer+_G_BUFSIZ) +static char* next_chunk = Buffer; // Start of available part of Buffer. + +char* form(const char* format, ...) +{ + int space_left = EndBuffer - next_chunk; + // If less that 25% of the space is available start over. + if (space_left < (_G_BUFSIZ>>2)) + next_chunk = Buffer; + char* buf = next_chunk; + + strstreambuf stream(buf, EndBuffer-buf-1, buf); + va_list ap; + va_start(ap, format); + int count = stream.vform(format, ap); + va_end(ap); + stream.sputc(0); + next_chunk = buf + stream.pcount(); + return buf; +} + +#define u_long unsigned long + +static char* itoa(unsigned long i, int size, int neg, int base) +{ + // Conservative estimate: If base==2, might need 8 characters + // for each input byte, but normally 3 is plenty. + int needed = size ? size + : (base >= 8 ? 3 : 8) * sizeof(unsigned long) + 2; + int space_left = EndBuffer - next_chunk; + if (space_left <= needed) + next_chunk = Buffer; // start over. + + char* buf = next_chunk; + + register char* ptr = buf+needed+1; + next_chunk = ptr; + + if (needed < (2+neg) || ptr > EndBuffer) + return NULL; + *--ptr = 0; + + if (i == 0) + *--ptr = '0'; + while (i != 0 && ptr > buf) { + int ch = i % base; + i = i / base; + if (ch >= 10) + ch += 'a' - 10; + else + ch += '0'; + *--ptr = ch; + } + if (neg) + *--ptr = '-'; + if (size == 0) + return ptr; + while (ptr > buf) + *--ptr = ' '; + return buf; +} + +char* dec(long i, int len /* = 0 */) +{ + if (i >= 0) return itoa((unsigned long)i, len, 0, 10); + else return itoa((unsigned long)(-i), len, 1, 10); +} +char* dec(int i, int len /* = 0 */) +{ + if (i >= 0) return itoa((unsigned long)i, len, 0, 10); + else return itoa((unsigned long)(-i), len, 1, 10); +} +char* dec(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 10); +} +char* dec(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 10); +} + +char* hex(long i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 16); +} +char* hex(int i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 16); +} +char* hex(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 16); +} +char* hex(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 16); +} + +char* oct(long i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 8); +} +char* oct(int i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 8); +} +char* oct(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 8); +} +char* oct(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 8); +} diff --git a/gnu/lib/libg++/iostream/stream.h b/gnu/lib/libg++/iostream/stream.h new file mode 100644 index 00000000000..5f87b7eef77 --- /dev/null +++ b/gnu/lib/libg++/iostream/stream.h @@ -0,0 +1,33 @@ +// $Id: stream.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ + +#ifndef _COMPAT_STREAM_H +#define _COMPAT_STREAM_H + +// Compatibility with old library. + +#define _STREAM_COMPAT +#include <iostream.h> + +extern char* form(const char*, ...); + +extern char* dec(long, int=0); +extern char* dec(int, int=0); +extern char* dec(unsigned long, int=0); +extern char* dec(unsigned int, int=0); + +extern char* hex(long, int=0); +extern char* hex(int, int=0); +extern char* hex(unsigned long, int=0); +extern char* hex(unsigned int, int=0); + +extern char* oct(long, int=0); +extern char* oct(int, int=0); +extern char* oct(unsigned long, int=0); +extern char* oct(unsigned int, int=0); + +char* chr(char ch, int width = 0); +char* str(const char* s, int width = 0); + +inline istream& WS(istream& str) { return ws(str); } + +#endif /* !_COMPAT_STREAM_H */ diff --git a/gnu/lib/libg++/iostream/streambuf.C b/gnu/lib/libg++/iostream/streambuf.C new file mode 100644 index 00000000000..0038f39190e --- /dev/null +++ b/gnu/lib/libg++/iostream/streambuf.C @@ -0,0 +1,666 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991, 1992 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#define _STREAM_COMPAT +#ifdef __GNUG__ +#pragma implementation +#endif +#include "ioprivate.h" +#include <string.h> + +void streambuf::_un_link() +{ + if (_flags & _S_LINKED) { + streambuf **f; + for (f = &_list_all; *f != NULL; f = &(*f)->xchain()) { + if (*f == this) { + *f = xchain(); + break; + } + } + _flags &= ~_S_LINKED; + } +} + +void streambuf::_link_in() +{ + if ((_flags & _S_LINKED) == 0) { + _flags |= _S_LINKED; + xchain() = _list_all; + _list_all = this; + } +} + +// Return minimum _pos markers +// Assumes the current get area is the main get area. +int streambuf::_least_marker() +{ + int least_so_far = _egptr - _eback; + for (register streammarker *mark = _markers; + mark != NULL; mark = mark->_next) + if (mark->_pos < least_so_far) + least_so_far = mark->_pos; + return least_so_far; +} + +// Switch current get area from backup buffer to (start of) main get area. + +void streambuf::switch_to_main_get_area() +{ + char *tmp; + _flags &= ~_S_IN_BACKUP; + // Swap _egptr and _other_egptr. + tmp= _egptr; _egptr= _other_egptr; _other_egptr= tmp; + // Swap _eback and _other_gbase. + tmp= _eback; _eback = _other_gbase; _other_gbase = tmp; + _gptr = _eback; +} + +// Switch current get area from main get area to (end of) backup area. + +void streambuf::switch_to_backup_area() +{ + char *tmp; + _flags |= _S_IN_BACKUP; + // Swap _egptr and _other_egptr. + tmp = _egptr; _egptr = _other_egptr; _other_egptr = tmp; + // Swap _gbase and _other_gbase. + tmp = _eback; _eback = _other_gbase; _other_gbase = tmp; + _gptr = _egptr; +} + +int streambuf::switch_to_get_mode() +{ + if (_pptr > _pbase) + if (overflow(EOF) == EOF) + return EOF; + if (in_backup()) { + _eback = _aux_limit; + } + else { + _eback = _base; + if (_pptr > _egptr) + _egptr = _pptr; + } + _gptr = _pptr; + + setp(_gptr, _gptr); + + _flags &= ~_S_CURRENTLY_PUTTING; + return 0; +} + +void streambuf::free_backup_area() +{ + if (in_backup()) + switch_to_main_get_area(); // Just in case. + delete [] _other_gbase; + _other_gbase = NULL; + _other_egptr = NULL; + _aux_limit = NULL; +} + +#if 0 +int streambuf::switch_to_put_mode() +{ + _pbase = _gptr; + _pptr = _gptr; + _epptr = in_backup() ? _egptr : _ebuf; // wrong if line- or un-buffered? + + _gptr = _egptr; + _eback = _egptr; + + _flags |= _S_CURRENTLY_PUTTING; + return 0; +} +#endif + +#ifdef _G_FRIEND_BUG +int __underflow(register streambuf *sb) { return __UNDERFLOW(sb); } +int __UNDERFLOW(register streambuf *sb) +#else +int __underflow(register streambuf *sb) +#endif +{ + if (sb->put_mode()) + if (sb->switch_to_get_mode() == EOF) return EOF; + if (sb->_gptr < sb->_egptr) + return *(unsigned char*)sb->_gptr; + if (sb->in_backup()) { + sb->switch_to_main_get_area(); + if (sb->_gptr < sb->_egptr) + return *sb->_gptr; + } + if (sb->have_markers()) { + // Append [_gbase.._egptr] to backup area. + int least_mark = sb->_least_marker(); + // needed_size is how much space we need in the backup area. + int needed_size = (sb->_egptr - sb->_eback) - least_mark; + int current_Bsize = sb->_other_egptr - sb->_other_gbase; + int avail; // Extra space available for future expansion. + if (needed_size > current_Bsize) { + avail = 0; // 100 ?? FIXME + char *new_buffer = new char[avail+needed_size]; + if (least_mark < 0) { + memcpy(new_buffer + avail, + sb->_other_egptr + least_mark, + -least_mark); + memcpy(new_buffer +avail - least_mark, + sb->_eback, + sb->_egptr - sb->_eback); + } + else + memcpy(new_buffer + avail, + sb->_eback + least_mark, + needed_size); + delete [] sb->_other_gbase; + sb->_other_gbase = new_buffer; + sb->_other_egptr = new_buffer + avail + needed_size; + } + else { + avail = current_Bsize - needed_size; + if (least_mark < 0) { + memmove(sb->_other_gbase + avail, + sb->_other_egptr + least_mark, + -least_mark); + memcpy(sb->_other_gbase + avail - least_mark, + sb->_eback, + sb->_egptr - sb->_eback); + } + else if (needed_size > 0) + memcpy(sb->_other_gbase + avail, + sb->_eback + least_mark, + needed_size); + } + // FIXME: Dubious arithmetic if pointers are NULL + sb->_aux_limit = sb->_other_gbase + avail; + // Adjust all the streammarkers. + int delta = sb->_egptr - sb->_eback; + for (register streammarker *mark = sb->_markers; + mark != NULL; mark = mark->_next) + mark->_pos -= delta; + } + else if (sb->have_backup()) + sb->free_backup_area(); + return sb->underflow(); +} + +#ifdef _G_FRIEND_BUG +int __overflow(register streambuf *sb, int c) { return __OVERFLOW(sb, c); } +int __OVERFLOW(register streambuf *sb, int c) +#else +int __overflow(streambuf* sb, int c) +#endif +{ + return sb->overflow(c); +} + +int streambuf::xsputn(register const char* s, int n) +{ + if (n <= 0) + return 0; + register int more = n; + for (;;) { + int count = _epptr - _pptr; // Space available. + if (count > 0) { + if (count > more) + count = more; + if (count > 20) { + memcpy(_pptr, s, count); + s += count; + _pptr += count; + } + else if (count <= 0) + count = 0; + else { + register char *p = _pptr; + for (register int i = count; --i >= 0; ) *p++ = *s++; + _pptr = p; + } + more -= count; + } + if (more == 0 || __overflow(this, (unsigned char)*s++) == EOF) + break; + more--; + } + return n - more; +} + +int streambuf::padn(char pad, int count) +{ +#define PADSIZE 16 + static char const blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static char const zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + char padbuf[PADSIZE]; + const char *padptr; + register int i; + + if (pad == ' ') + padptr = blanks; + else if (pad == '0') + padptr = zeroes; + else { + for (i = PADSIZE; --i >= 0; ) padbuf[i] = pad; + padptr = padbuf; + } + for (i = count; i >= PADSIZE; i -= PADSIZE) + if (sputn(padptr, PADSIZE) != PADSIZE) + return EOF; + if (i > 0 && sputn(padptr, i) != i) + return EOF; + return pad; +} + +int streambuf::xsgetn(char* s, int n) +{ + register int more = n; + for (;;) { + int count = _egptr - _gptr; // Data available. + if (count > 0) { + if (count > more) + count = more; + if (count > 20) { + memcpy(s, _gptr, count); + s += count; + _gptr += count; + } + else if (count <= 0) + count = 0; + else { + register char *p = _gptr; + for (register int i = count; --i >= 0; ) *s++ = *p++; + _gptr = p; + } + more -= count; + } + if (more == 0 || __underflow(this) == EOF) + break; + } + return n - more; +} + +int streambuf::ignore(int n) +{ + register int more = n; + for (;;) { + int count = _egptr - _gptr; // Data available. + if (count > 0) { + if (count > more) + count = more; + _gptr += count; + more -= count; + } + if (more == 0 || __underflow(this) == EOF) + break; + } + return n - more; +} + +int streambuf::sync() +{ + if (gptr() == egptr() && pptr() == pbase()) + return 0; + return EOF; +} + +int streambuf::pbackfail(int c) +{ + if (_gptr > _eback) + _gptr--; + else if (seekoff(-1, ios::cur, ios::in) == EOF) + return EOF; + if (c != EOF && *_gptr != c) + *_gptr = c; + return (unsigned char)c; +} + +streambuf* streambuf::setbuf(char* p, int len) +{ + if (sync() == EOF) + return NULL; + if (p == NULL || len == 0) { + unbuffered(1); + setb(_shortbuf, _shortbuf+1, 0); + } + else { + unbuffered(0); + setb(p, p+len, 0); + } + setp(0, 0); + setg(0, 0, 0); + return this; +} + +streampos streambuf::seekpos(streampos pos, int mode) +{ + return seekoff(pos, ios::beg, mode); +} + +void streambuf::setb(char* b, char* eb, int a) +{ + if (_base && !(_flags & _S_USER_BUF)) + FREE_BUF(_base); + _base = b; + _ebuf = eb; + if (a) + _flags &= ~_S_USER_BUF; + else + _flags |= _S_USER_BUF; +} + +int streambuf::doallocate() +{ + char *buf = ALLOC_BUF(_G_BUFSIZ); + if (buf == NULL) + return EOF; + setb(buf, buf+_G_BUFSIZ, 1); + return 1; +} + +void streambuf::doallocbuf() +{ + if (base() || (!unbuffered() && doallocate() != EOF)) return; + setb(_shortbuf, _shortbuf+1, 0); +} + +streambuf::streambuf(int flags) +{ + _flags = _IO_MAGIC|flags; + _base = NULL; + _ebuf = NULL; + _eback = NULL; + _gptr = NULL; + _egptr = NULL; + _pbase = NULL; + _pptr = NULL; + _epptr = NULL; + _chain = NULL; // Not necessary. + + _other_gbase = NULL; + _aux_limit = NULL; + _other_egptr = NULL; + _markers = NULL; + _cur_column = 0; +} + +streambuf::~streambuf() +{ + if (_base && !(_flags & _S_USER_BUF)) + FREE_BUF(_base); + + for (register streammarker *mark = _markers; + mark != NULL; mark = mark->_next) + mark->_sbuf = NULL; + +} + +streampos +streambuf::seekoff(streamoff, _seek_dir, int mode /*=ios::in|ios::out*/) +{ + return EOF; +} + +int streambuf::sputbackc(char c) +{ + if (_gptr > _eback && (unsigned char)_gptr[-1] == (unsigned char)c) { + _gptr--; + return (unsigned char)c; + } + return pbackfail(c); +} + +int streambuf::sungetc() +{ + if (_gptr > _eback) { + _gptr--; + return (unsigned char)*_gptr; + } + else + return pbackfail(EOF); +} + +#if 0 /* Work in progress */ +void streambuf::collumn(int c) +{ + if (c == -1) + _collumn = -1; + else + _collumn = c - (_pptr - _pbase); +} +#endif + + +int streambuf::get_column() +{ + if (_cur_column) + return __adjust_column(_cur_column - 1, pbase(), pptr() - pbase()); + return -1; +} + +int streambuf::set_column(int i) +{ + _cur_column = i+1; + return 0; +} + +int streambuf::flush_all() +{ + int result = 0; + for (streambuf *sb = _list_all; sb != NULL; sb = sb->xchain()) + if (sb->overflow(EOF) == EOF) + result = EOF; + return result; +} + +void streambuf::flush_all_linebuffered() +{ + for (streambuf *sb = _list_all; sb != NULL; sb = sb->xchain()) + if (sb->linebuffered()) + sb->overflow(EOF); +} + +int backupbuf::underflow() +{ + return EOF; +} + +int backupbuf::overflow(int c) +{ + return EOF; +} + +streammarker::streammarker(streambuf *sb) +{ + _sbuf = sb; + if (!(sb->xflags() & _S_IS_BACKUPBUF)) { + set_streampos(sb->seekoff(0, ios::cur, ios::in)); + _next = 0; + } + else { + if (sb->put_mode()) + sb->switch_to_get_mode(); + if (((backupbuf*)sb)->in_backup()) + set_offset(sb->_gptr - sb->_egptr); + else + set_offset(sb->_gptr - sb->_eback); + + // Should perhaps sort the chain? + _next = ((backupbuf*)sb)->_markers; + ((backupbuf*)sb)->_markers = this; + } +} + +streammarker::~streammarker() +{ + if (saving()) { + // Unlink from sb's chain. + register streammarker **ptr = &((backupbuf*)_sbuf)->_markers; + for (; ; ptr = &(*ptr)->_next) + if (*ptr == NULL) + break; + else if (*ptr == this) { + *ptr = _next; + return; + } + } +#if 0 + if _sbuf has a backup area that is no longer needed, should we delete + it now, or wait until underflow()? +#endif +} + +#define BAD_DELTA EOF + +int streammarker::delta(streammarker& other_mark) +{ + if (_sbuf != other_mark._sbuf) + return BAD_DELTA; + if (saving() && other_mark.saving()) + return _pos - other_mark._pos; + else if (!saving() && !other_mark.saving()) + return _spos - other_mark._spos; + else + return BAD_DELTA; +} + +int streammarker::delta() +{ + if (_sbuf == NULL) + return BAD_DELTA; + if (saving()) { + int cur_pos; + if (_sbuf->in_backup()) + cur_pos = _sbuf->_gptr - _sbuf->_egptr; + else + cur_pos = _sbuf->_gptr - _sbuf->_eback; + return _pos - cur_pos; + } + else { + if (_spos == EOF) + return BAD_DELTA; + int cur_pos = _sbuf->seekoff(0, ios::cur); + if (cur_pos == EOF) + return BAD_DELTA; + return _pos - cur_pos; + } +} + +int streambuf::seekmark(streammarker& mark, int delta /* = 0 */) +{ + if (mark._sbuf != this) + return EOF; + if (!mark.saving()) { + return seekpos(mark._spos, ios::in); + } + else if (mark._pos >= 0) { + if (in_backup()) + switch_to_main_get_area(); + _gptr = _eback + mark._pos; + } + else { + if (!in_backup()) + switch_to_backup_area(); + _gptr = _egptr + mark._pos; + } + return 0; +} + +void streambuf::unsave_markers() +{ + register streammarker *mark =_markers; + if (_markers) { + streampos offset = seekoff(0, ios::cur, ios::in); + if (offset != EOF) { + offset += eGptr() - Gbase(); + for ( ; mark != NULL; mark = mark->_next) + mark->set_streampos(mark->_pos + offset); + } + else { + for ( ; mark != NULL; mark = mark->_next) + mark->set_streampos(EOF); + } + _markers = 0; + } + + free_backup_area(); +} + +int backupbuf::pbackfail(int c) +{ + if (_gptr <= _eback) { + // Need to handle a filebuf in write mode (switch to read mode). FIXME! + + if (have_backup() && !in_backup()) { + switch_to_backup_area(); + } + if (!have_backup()) { + // No backup buffer: allocate one. + // Use short buffer, if unused? (probably not) FIXME + int backup_size = 128; + _other_gbase = new char [backup_size]; + _other_egptr = _other_gbase + backup_size; + _aux_limit = _other_egptr; + switch_to_backup_area(); + } + else if (gptr() <= eback()) { + // Increase size of existing backup buffer. + size_t new_size; + size_t old_size = egptr() - eback(); + new_size = 2 * old_size; + char* new_buf = new char [new_size]; + memcpy(new_buf+(new_size-old_size), eback(), old_size); + delete [] eback(); + setg(new_buf, new_buf+(new_size-old_size), new_buf+new_size); + _aux_limit = _gptr; + } + } + _gptr--; + if (c != EOF && *_gptr != c) + *_gptr = c; + return (unsigned char)*_gptr; +} + +unsigned __adjust_column(unsigned start, const char *line, int count) +{ + register const char *ptr = line + count; + while (ptr > line) + if (*--ptr == '\n') + return line + count - ptr - 1; + return start + count; +} + +int ios::readable() { return !(rdbuf()->_flags & _S_NO_READS); } +int ios::writable() { return !(rdbuf()->_flags & _S_NO_WRITES); } +int ios::is_open() { return rdbuf() + && (rdbuf()->_flags & _S_NO_READS+_S_NO_WRITES) + != _S_NO_READS+_S_NO_WRITES; } + +#if defined(linux) +#define IO_CLEANUP ; +#endif + +#ifdef IO_CLEANUP + IO_CLEANUP +#else +struct __io_defs { + __io_defs() { } + ~__io_defs() { streambuf::flush_all(); } +}; +__io_defs io_defs__; +#endif diff --git a/gnu/lib/libg++/iostream/streambuf.h b/gnu/lib/libg++/iostream/streambuf.h new file mode 100644 index 00000000000..6beaeb6284c --- /dev/null +++ b/gnu/lib/libg++/iostream/streambuf.h @@ -0,0 +1,497 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: streambuf.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ + +#ifndef _STREAMBUF_H +#define _STREAMBUF_H +#ifdef __GNUG__ +#pragma interface +#endif + +/* #define _G_IO_THROW */ /* Not implemented: ios::failure */ + +#include <_G_config.h> +#ifdef _G_NEED_STDARG_H +#include <stdarg.h> +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#ifdef __GNUC__ +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +class ostream; class streambuf; class backupbuf; + +// In case some header files defines these as macros. +#undef open +#undef close + +#ifdef _G_FRIEND_BUG +extern int __UNDERFLOW(streambuf*); +extern int __OVERFLOW(streambuf*, int); +#endif +extern "C" int __underflow(streambuf*); +extern "C" int __overflow(streambuf*, int); + +typedef _G_off_t streamoff; +typedef _G_off_t streampos; // Should perhaps be _G_fpos_t ? + +typedef unsigned long __fmtflags; +typedef unsigned char __iostate; + +struct _ios_fields { // The data members of an ios. + streambuf *_strbuf; + ostream* _tie; + int _width; + __fmtflags _flags; + _G_wchar_t _fill; + __iostate _state; + __iostate _exceptions; + int _precision; +}; + +#define _IOS_GOOD 0 +#define _IOS_EOF 1 +#define _IOS_FAIL 2 +#define _IOS_BAD 4 + +#define _IOS_INPUT 1 +#define _IOS_OUTPUT 2 +#define _IOS_ATEND 4 +#define _IOS_APPEND 8 +#define _IOS_TRUNC 16 +#define _IOS_NOCREATE 32 +#define _IOS_NOREPLACE 64 +#define _IOS_BIN 128 + +#ifdef _STREAM_COMPAT +enum state_value { + _good = _IOS_GOOD, + _eof = _IOS_EOF, + _fail = _IOS_FAIL, + _bad = _IOS_BAD }; +enum open_mode { + input = _IOS_INPUT, + output = _IOS_OUTPUT, + atend = _IOS_ATEND, + append = _IOS_APPEND }; +#endif + +class ios : public _ios_fields { + public: + typedef __fmtflags fmtflags; + typedef int iostate; + typedef int openmode; + typedef int streamsize; + enum io_state { + goodbit = _IOS_GOOD, + eofbit = _IOS_EOF, + failbit = _IOS_FAIL, + badbit = _IOS_BAD }; + enum open_mode { + in = _IOS_INPUT, + out = _IOS_OUTPUT, + ate = _IOS_ATEND, + app = _IOS_APPEND, + trunc = _IOS_TRUNC, + nocreate = _IOS_NOCREATE, + noreplace = _IOS_NOREPLACE, + bin = _IOS_BIN }; + enum seek_dir { beg, cur, end}; + // ANSI: typedef enum seek_dir seekdir; etc + enum { skipws=01, left=02, right=04, internal=010, + dec=020, oct=040, hex=0100, + showbase=0200, showpoint=0400, uppercase=01000, showpos=02000, + scientific=04000, fixed=010000, unitbuf=020000, stdio=040000, + dont_close=0100000 //Don't delete streambuf on stream destruction + }; + enum { // Masks. + basefield=dec+oct+hex, + floatfield = scientific+fixed, + adjustfield = left+right+internal + }; + +#ifdef _G_IO_THROW + class failure : public xmsg { + ios* _stream; + public: + failure(ios* stream) { _stream = stream; } + failure(string cause, ios* stream) { _stream = stream; } + ios* rdios() const { return _stream; } + }; +#endif + + ostream* tie() const { return _tie; } + ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; } + + // Methods to change the format state. + _G_wchar_t fill() const { return (_G_wchar_t)_fill; } + _G_wchar_t fill(_G_wchar_t newf) + {_G_wchar_t oldf = (_G_wchar_t)_fill; _fill = (char)newf; return oldf;} + fmtflags flags() const { return _flags; } + fmtflags flags(fmtflags new_val) { + fmtflags old_val = _flags; _flags = new_val; return old_val; } + int precision() const { return _precision; } + int precision(int newp) { + unsigned short oldp = _precision; _precision = (unsigned short)newp; + return oldp; } + fmtflags setf(fmtflags val) { + fmtflags oldbits = _flags; + _flags |= val; return oldbits; } + fmtflags setf(fmtflags val, fmtflags mask) { + fmtflags oldbits = _flags; + _flags = (_flags & ~mask) | (val & mask); return oldbits; } + fmtflags unsetf(fmtflags mask) { + fmtflags oldbits = _flags & mask; + _flags &= ~mask; return oldbits; } + int width() const { return _width; } + int width(int val) { int save = _width; _width = val; return save; } + +#ifdef _G_IO_THROW + void _throw_failure() { throw new ios::failure(this); } +#else + void _throw_failure() { } +#endif + + streambuf* rdbuf() const { return _strbuf; } + void clear(iostate state = 0) { + _state = _strbuf ? state : state|badbit; + if (_state & _exceptions) _throw_failure(); } + void set(iostate flag) { _state |= flag; + if (_state & _exceptions) _throw_failure(); } + void setstate(iostate flag) { _state |= flag; // ANSI + if (_state & _exceptions) _throw_failure(); } + int good() const { return _state == 0; } + int eof() const { return _state & ios::eofbit; } + int fail() const { return _state & (ios::badbit|ios::failbit); } + int bad() const { return _state & ios::badbit; } + iostate rdstate() const { return _state; } + operator void*() const { return fail() ? (void*)0 : (void*)(-1); } + int operator!() const { return fail(); } + iostate exceptions() const { return _exceptions; } + void exceptions(iostate enable) { + _exceptions = enable; + if (_state & _exceptions) _throw_failure(); } + + static int sync_with_stdio(int on); + static void sync_with_stdio() { sync_with_stdio(1); } + +#ifdef _STREAM_COMPAT + void unset(state_value flag) { _state &= ~flag; } + void close(); + int is_open(); + int readable(); + int writable(); +#endif + + // Used to initialize standard streams. Not needed in this implementation. + class Init { + public: + Init () { } + }; + + protected: + ios(streambuf* sb = 0, ostream* tie = 0); + virtual ~ios(); + void init(streambuf* sb) { _state=0; _strbuf=sb; } +}; + +#if __GNUG__==1 +typedef int _seek_dir; +#else +typedef ios::seek_dir _seek_dir; +#endif + +// Magic numbers and bits for the _flags field. +// The magic numbers use the high-order bits of _flags; +// the remaining bits are abailable for variable flags. +// Note: The magic numbers must all be negative if stdio +// emulation is desired. + +#define _IO_MAGIC 0xFBAD0000 /* Magic number */ +#define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */ +#define _IO_MAGIC_MASK 0xFFFF0000 +#define _S_USER_BUF 1 /* User owns buffer; don't delete it on close. */ +#define _S_UNBUFFERED 2 +#define _S_NO_READS 4 /* Reading not allowed */ +#define _S_NO_WRITES 8 /* Writing not allowd */ +#define _S_EOF_SEEN 0x10 +#define _S_ERR_SEEN 0x20 +#define _S_DELETE_DONT_CLOSE 0x40 +#define _S_LINKED 0x80 // Set if linked (using _chain) to streambuf::_list_all. +#define _S_IN_BACKUP 0x100 +#define _S_LINE_BUF 0x200 +#define _S_TIED_PUT_GET 0x400 // Set if put and get pointer logicly tied. +#define _S_CURRENTLY_PUTTING 0x800 +#define _S_IS_APPENDING 0x1000 +#define _S_IS_BACKUPBUF 0x4000 +#define _S_IS_FILEBUF 0x8000 + +// A streammarker remembers a position in a buffer. +// You are guaranteed to be able to seek back to it if it is saving(). +class streammarker { + friend class streambuf; +#ifdef _G_FRIEND_BUG + friend int __UNDERFLOW(streambuf*); +#else + friend int __underflow(streambuf*); +#endif + struct streammarker *_next; // Only if saving() + streambuf *_sbuf; // Only valid if saving(). + streampos _spos; // -2: means that _pos is valid. + void set_streampos(streampos sp) { _spos = sp; } + void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); } + // If _pos >= 0, it points to _buf->Gbase()+_pos. + // if _pos < 0, it points to _buf->eBptr()+_pos. + int _pos; + public: + streammarker(streambuf *sb); + ~streammarker(); + int saving() { return _spos == -2; } + int delta(streammarker&); + int delta(); +}; + +struct __streambuf { + // NOTE: If this is changed, also change __FILE in stdio/stdio.h! + int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ + char* _gptr; /* Current get pointer */ + char* _egptr; /* End of get area. */ + char* _eback; /* Start of putback+get area. */ + char* _pbase; /* Start of put area. */ + char* _pptr; /* Current put pointer. */ + char* _epptr; /* End of put area. */ + char* _base; /* Start of reserve area. */ + char* _ebuf; /* End of reserve area. */ + struct streambuf *_chain; + + // The following fields are used to support backing up and undo. + friend class streammarker; + char *_other_gbase; // Pointer to start of non-current get area. + char *_aux_limit; // Pointer to first valid character of backup area, + char *_other_egptr; // Pointer to end of non-current get area. + streammarker *_markers; + +#define __HAVE_COLUMN /* temporary */ + // 1+column number of pbase(); 0 is unknown. + unsigned short _cur_column; + char _unused; + char _shortbuf[1]; +}; + +extern unsigned __adjust_column(unsigned start, const char *line, int count); + +struct streambuf : public __streambuf { + friend class ios; + friend class istream; + friend class ostream; + friend class streammarker; +#ifdef _G_FRIEND_BUG + friend int __UNDERFLOW(streambuf*); +#else + friend int __underflow(streambuf*); +#endif + protected: + static streambuf* _list_all; /* List of open streambufs. */ + streambuf*& xchain() { return _chain; } + void _un_link(); + void _link_in(); + char* gptr() const { return _gptr; } + char* pptr() const { return _pptr; } + char* egptr() const { return _egptr; } + char* epptr() const { return _epptr; } + char* pbase() const { return _pbase; } + char* eback() const { return _eback; } + char* base() const { return _base; } + char* ebuf() const { return _ebuf; } + int blen() const { return _ebuf - _base; } + void xput_char(char c) { *_pptr++ = c; } + int xflags() { return _flags; } + int xflags(int f) { int fl = _flags; _flags = f; return fl; } + void xsetflags(int f) { _flags |= f; } + void xsetflags(int f, int mask) { _flags = (_flags & ~mask) | (f & mask); } + void gbump(int n) { _gptr += n; } + void pbump(int n) { _pptr += n; } + void setb(char* b, char* eb, int a=0); + void setp(char* p, char* ep) { _pbase=_pptr=p; _epptr=ep; } + void setg(char* eb, char* g, char *eg) { _eback=eb; _gptr=g; _egptr=eg; } + char *shortbuf() { return _shortbuf; } + + int in_backup() { return _flags & _S_IN_BACKUP; } + // The start of the main get area: FIXME: wrong for write-mode filebuf? + char *Gbase() { return in_backup() ? _other_gbase : _eback; } + // The end of the main get area: + char *eGptr() { return in_backup() ? _other_egptr : _egptr; } + // The start of the backup area: + char *Bbase() { return in_backup() ? _eback : _other_gbase; } + char *Bptr() { return _aux_limit; } + // The end of the backup area: + char *eBptr() { return in_backup() ? _egptr : _other_egptr; } + char *Nbase() { return _other_gbase; } + char *eNptr() { return _other_egptr; } + int have_backup() { return _other_gbase != NULL; } + int have_markers() { return _markers != NULL; } + int _least_marker(); + void switch_to_main_get_area(); + void switch_to_backup_area(); + void free_backup_area(); + void unsave_markers(); // Make all streammarkers !saving(). + int put_mode() { return _flags & _S_CURRENTLY_PUTTING; } + int switch_to_get_mode(); + + streambuf(int flags=0); + public: + static int flush_all(); + static void flush_all_linebuffered(); // Flush all line buffered files. + virtual int underflow() = 0; // Leave public for now + virtual int overflow(int c = EOF) = 0; // Leave public for now + virtual int doallocate(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); + int seekmark(streammarker& mark, int delta = 0); + int sputbackc(char c); + int sungetc(); + virtual ~streambuf(); + int unbuffered() { return _flags & _S_UNBUFFERED ? 1 : 0; } + int linebuffered() { return _flags & _S_LINE_BUF ? 1 : 0; } + void unbuffered(int i) + { if (i) _flags |= _S_UNBUFFERED; else _flags &= ~_S_UNBUFFERED; } + void linebuffered(int i) + { if (i) _flags |= _S_LINE_BUF; else _flags &= ~_S_LINE_BUF; } + int allocate() { // For AT&T compatibility + if (base() || unbuffered()) return 0; + else return doallocate(); } + // Allocate a buffer if needed; use _shortbuf if appropriate. + void allocbuf() { if (base() == NULL) doallocbuf(); } + void doallocbuf(); + virtual int sync(); + virtual int pbackfail(int c); + virtual streambuf* setbuf(char* p, int len); + int in_avail() { return _egptr - _gptr; } + int out_waiting() { return _pptr - _pbase; } + virtual int xsputn(const char* s, int n); + int sputn(const char* s, int n) { return xsputn(s, n); } + int padn(char pad, int n); // Emit 'n' copies of 'pad'. + virtual int xsgetn(char* s, int n); + int sgetn(char* s, int n) { return xsgetn(s, n); } + int ignore(int); + virtual int get_column(); + virtual int set_column(int); + long sgetline(char* buf, _G_size_t n, char delim, int putback_delim); + int sbumpc() { + if (_gptr >= _egptr && __underflow(this) == EOF) return EOF; + else return *(unsigned char*)_gptr++; } + int sgetc() { + if (_gptr >= _egptr && __underflow(this) == EOF) return EOF; + else return *(unsigned char*)_gptr; } + int snextc() { + if (_gptr >= _egptr && __underflow(this) == EOF) return EOF; + else return _gptr++, sgetc(); } + int sputc(int c) { + if (_pptr >= _epptr) return __overflow(this, (unsigned char)c); + else return *_pptr++ = c, (unsigned char)c; } + void stossc() { if (_gptr < _egptr) _gptr++; } + int vscan(char const *fmt0, _G_va_list ap, ios* stream = NULL); + int scan(char const *fmt0 ...); + int vform(char const *fmt0, _G_va_list ap); + int form(char const *fmt0 ...); +#if 0 /* Work in progress */ + int collumn(); // Current collumn number (of put pointer). -1 is unknown. + void collumn(int c); // Set collumn number of put pointer to c. +#endif +}; + +// A backupbuf is a streambuf with full backup and savepoints on reading. +// All standard streambufs in the GNU iostream library are backupbufs. + +// A backupbuf may have two get area: +// - The main get area, and (sometimes) the putback area. +// Whichever one of these contains the gptr is the current get area; +// the other one is the non-current get area. + +class backupbuf : public streambuf { + friend class streammarker; + protected: + backupbuf(int flags=0) : streambuf(flags|_S_IS_BACKUPBUF) { } + public: + virtual int pbackfail(int c); + virtual int underflow(); + virtual int overflow(int c = EOF); +}; + +struct __file_fields { + short _fileno; + int _blksize; + _G_off_t _offset; +// char* _save_gptr; char* _save_egptr; +}; + +class filebuf : public backupbuf { + protected: + struct __file_fields _fb; + void init(); + public: + static const int openprot; // Non-ANSI AT&T-ism: Default open protection. + filebuf(); + filebuf(int fd); + filebuf(int fd, char* p, int len); + ~filebuf(); + filebuf* attach(int fd); + filebuf* open(const char *filename, const char *mode); + filebuf* open(const char *filename, ios::openmode mode, int prot = 0664); + virtual int underflow(); + virtual int overflow(int c = EOF); + int is_open() const { return _fb._fileno >= 0; } + int fd() const { return is_open() ? _fb._fileno : EOF; } + filebuf* close(); + virtual int doallocate(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streambuf* setbuf(char* p, int len); + int xsputn(const char* s, int n); + int xsgetn(char* s, int n); + virtual int sync(); + protected: // See documentation in filebuf.C. +// virtual int pbackfail(int c); + int is_reading() { return eback() != egptr(); } + char* cur_ptr() { return is_reading() ? gptr() : pptr(); } + /* System's idea of pointer */ + char* file_ptr() { return eGptr(); } + int do_write(const char *data, int to_do); + int do_flush() { return do_write(_pbase, _pptr-_pbase); } + // Low-level operations (Usually invoke system calls.) + virtual _G_ssize_t sys_read(char* buf, _G_size_t size); + virtual _G_fpos_t sys_seek(_G_fpos_t, _seek_dir); + virtual _G_ssize_t sys_write(const void*, long); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +}; + +inline ios::ios(streambuf* sb /* = 0 */, ostream* tie_to /* = 0 */) { + _state = sb ? ios::goodbit : ios::badbit; _exceptions=0; + _strbuf=sb; _tie = tie_to; _width=0; _fill=' '; + _flags=ios::skipws|ios::dec; _precision=6; } +inline ios::~ios() { + if (!(_flags & (unsigned int)ios::dont_close)) delete _strbuf; } + +#endif /* _STREAMBUF_H */ diff --git a/gnu/lib/libg++/iostream/strstream.C b/gnu/lib/libg++/iostream/strstream.C new file mode 100644 index 00000000000..d5a57137d52 --- /dev/null +++ b/gnu/lib/libg++/iostream/strstream.C @@ -0,0 +1,237 @@ +// This is part of the iostream library, providing input/output for C++. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "ioprivate.h" +#include <strstream.h> + +static void* default_alloc(_G_size_t size) +{ + return (void*)new char[size]; +} + +static void default_free(void* ptr) +{ + delete [] (char*)ptr; +} + +istrstream::istrstream(const char *cp, int n) +{ + init(new strstreambuf(cp, n)); +} + +ostrstream::ostrstream() +{ + init(new strstreambuf()); +} + +strstreambase::strstreambase(char *cp, int n, int mode) +{ + char *pstart; + if (mode == ios::app || mode == ios::ate) + pstart = cp + strlen(cp); + else + pstart = cp; + init(new strstreambuf(cp, n, pstart)); +} + +char *strstreambuf::str() +{ + freeze(1); + return base(); +} + +_G_size_t strstreambuf::pcount() +{ + _G_size_t put_len = pptr() - pbase(); + if (put_len < _len) put_len = _len; + return put_len; +} + +int strstreambuf::overflow(int c /* = EOF */) +{ + const int flush_only = c == EOF; + if (_flags & _S_NO_WRITES) + return flush_only ? 0 : EOF; + size_t pos = pptr() - pbase(); + size_t get_pos = gptr() - pbase(); + if (pos > _len) _len = pos; + if (pos >= blen() + flush_only) { + char *new_buf; + size_t new_size = 2 * blen(); + if (frozen()) /* not allowed to enlarge */ + return EOF; + new_buf = (char*)(*_allocate_buffer)(new_size); + memcpy(new_buf, base(), blen()); + if (new_buf == NULL) { +// __ferror(fp) = 1; + return EOF; + } +#if 0 + if (lenp == &_len) /* use '\0'-filling */ + memset(new_buf + pos, 0, blen() - pos); +#endif + if (_base) { + (*_free_buffer)(_base); + _base = NULL; // So setb() won't try to delete _base. + } + setb(new_buf, new_buf + new_size, 1); + } + + setp(base(), ebuf()); + pbump(pos); + setg(base(), base() + get_pos, base() + _len); + if (!flush_only) { + *pptr() = (unsigned char) c; + pbump(1); + } + return c; +} + +int strstreambuf::underflow() +{ + size_t ppos = pptr() - pbase(); + if (ppos > _len) _len = ppos; + setg(base(), gptr(), base() + _len); + if (gptr() < egptr()) + return *gptr(); + else + return EOF; +} + + +void strstreambuf::init_dynamic(_alloc_type alloc, _free_type free, + int initial_size) + +{ + _len = 0; + if (initial_size < 16) + initial_size = 16; + _allocate_buffer = alloc ? alloc : default_alloc; + _free_buffer = free ? free : default_free; + char * buf = (char*)(*_allocate_buffer)(initial_size); + setb(buf, buf + initial_size, 1); + setp(buf, buf + initial_size); + setg(buf, buf, buf); +} + +void strstreambuf::init_static(char *ptr, int size, char *pstart) +{ + if (size == 0) + size = strlen(ptr); + else if (size < 0) { + // If size is negative 'the characters are assumed to + // continue indefinitely.' This is kind of messy ... +#if 1 + size = 512; + // Try increasing powers of 2, as long as we don't wrap around. + // This can lose in pathological cases (ptr near the end + // of the address space). A better solution might be to + // adjust the size on underflow/overflow. FIXME. + for (int s; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) + size = s; + size = s; +#else + // The following semi-portable kludge assumes that + // sizeof(unsigned long) == sizeof(char*). Hence, + // (unsigned long)(-1) should be the largest possible address. + unsigned long highest = (unsigned long)(-1); + // Pointers are signed on some brain-damaged systems, in + // which case we divide by two to get the maximum signed address. + if ((char*)highest < ptr) + highest >>= 1; + size = (char*)highest - ptr; +#endif + } + setb(ptr, ptr+size); + if (pstart) { + setp(ptr, ebuf()); + pbump(pstart-ptr); + setg(ptr, ptr, pstart); + } + else { + setp(ptr, ptr); + setg(ptr, ptr, ebuf()); + } + _len = egptr() - ptr; +} + +void strstreambuf::init_static (const char *ptr, int size) +{ + init_static((char*)ptr, size, NULL); + xsetflags(_S_NO_WRITES); +} + +strstreambuf::~strstreambuf() +{ + if (_base && !(_flags & _S_USER_BUF)) + (_free_buffer)(_base); + _base = NULL; +} + +streampos strstreambuf::seekoff(streamoff off, _seek_dir dir, + int mode /*=ios::in|ios::out*/) +{ + size_t cur_size = pcount(); + streampos new_pos = EOF; + + // Move the get pointer, if requested. + if (mode & ios::in) { + switch (dir) { + case ios::end: + off += cur_size; + break; + case ios::cur: + off += gptr() - pbase(); + break; + default: /*case ios::beg: */ + break; + } + if (off < 0 || (size_t)off > cur_size) + return EOF; + setg(base(), base() + off, base() + cur_size); + new_pos = off; + } + + // Move the put pointer, if requested. + if (mode & ios::out) { + switch (dir) { + case ios::end: + off += cur_size; + break; + case ios::cur: + off += pptr() - pbase(); + break; + default: /*case ios::beg: */ + break; + } + if (off < 0 || (size_t)off > cur_size) + return EOF; + pbump(base() + off - pptr()); + new_pos = off; + } + return new_pos; +} + +int strstreambuf::pbackfail(int c) +{ + if ((_flags & _S_NO_WRITES) && c != EOF) + return EOF; + return backupbuf::pbackfail(c); +} diff --git a/gnu/lib/libg++/iostream/strstream.h b/gnu/lib/libg++/iostream/strstream.h new file mode 100644 index 00000000000..9302a60ee59 --- /dev/null +++ b/gnu/lib/libg++/iostream/strstream.h @@ -0,0 +1,105 @@ +// This is part of the iostream library, providing -*- C++ -*- input/output. +// Copyright (C) 1991 Per Bothner. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id: strstream.h,v 1.1 1995/10/18 08:38:14 deraadt Exp $ + +#ifndef __STRSTREAM_H +#define __STRSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <iostream.h> + +class strstreambuf : public backupbuf { + _G_size_t _len; // The current length is max(_len, _pptr-_pbase). + typedef void *(*_alloc_type)(_G_size_t); + typedef void (*_free_type)(void*); + _alloc_type _allocate_buffer; + _free_type _free_buffer; + void init_dynamic(_alloc_type alloc, _free_type free, + int initial_size = 128); + void init_static(char *ptr, int size, char *pstart); + void init_static(const char *ptr, int size); + protected: + int is_static() const { return _allocate_buffer == (_alloc_type)0; } + virtual int overflow(int = EOF); + virtual int underflow(); + virtual int pbackfail(int c); + public: + virtual ~strstreambuf(); + strstreambuf() { init_dynamic(0, 0); } + strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); } + strstreambuf(void *(*alloc)(_G_size_t), void (*free)(void*)) + { init_dynamic(alloc, free); } + strstreambuf(char *ptr, int size, char *pstart = NULL) + { init_static(ptr, size, pstart); } + strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL) + { init_static((char*)ptr, size, (char*)pstart); } + strstreambuf(const char *ptr, int size) + { init_static(ptr, size); } + strstreambuf(const unsigned char *ptr, int size) + { init_static((const char*)ptr, size); } +#ifndef _G_BROKEN_SIGNED_CHAR + strstreambuf(signed char *ptr, int size, signed char *pstart = NULL) + { init_static((char*)ptr, size, (char*)pstart); } + strstreambuf(const signed char *ptr, int size) + { init_static((const char*)ptr, size); } +#endif + // Note: frozen() is always true if is_static(). + int frozen() { return _flags & _S_USER_BUF ? 1 : 0; } + void freeze(int n=1) + { if (!is_static()) + { if (n) _flags |= _S_USER_BUF; else _flags &= ~_S_USER_BUF; } } + _G_size_t pcount(); + char *str(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); +}; + +class strstreambase : virtual public ios { + public: + strstreambuf* rdbuf() { return (strstreambuf*)_strbuf; } + protected: + strstreambase() { } + strstreambase(char *cp, int n, int mode=ios::out); +}; + +class istrstream : public strstreambase, public istream { + public: + istrstream(const char*, int=0); +}; + +class ostrstream : public strstreambase, public ostream { + public: + ostrstream(); + ostrstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){} + _G_size_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); } + char *str() { return ((strstreambuf*)_strbuf)->str(); } + void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); } + int frozen() { return ((strstreambuf*)_strbuf)->frozen(); } +}; + +class strstream : public strstreambase, public iostream { + public: + strstream() : strstreambase() { init(new strstreambuf()); } + strstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){} + _G_size_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); } + char *str() { return ((strstreambuf*)_strbuf)->str(); } + void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); } + int frozen() { return ((strstreambuf*)_strbuf)->frozen(); } +}; + +#endif /*!__STRSTREAM_H*/ diff --git a/gnu/lib/libmalloc/COPYING.LIB b/gnu/lib/libmalloc/COPYING.LIB new file mode 100644 index 00000000000..eb685a5ec98 --- /dev/null +++ b/gnu/lib/libmalloc/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gnu/lib/libmalloc/ChangeLog b/gnu/lib/libmalloc/ChangeLog new file mode 100644 index 00000000000..260c9797ab8 --- /dev/null +++ b/gnu/lib/libmalloc/ChangeLog @@ -0,0 +1,291 @@ +Wed Jun 2 17:45:38 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/Makefile (%.gz): Renamed target from %.z; use -v flag. + (malloc/ChangeLog): Use mv -f. + +Mon May 31 21:49:04 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/mtrace.c: #include <stdio.h>; malloc.h no longer does. + +Sun May 30 20:04:50 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/malloc.c (malloc): #if 0 out ``if (SIZE == 0) return NULL''. + + * malloc/malloc.h [_MALLOC_INTERNAL]: Don't include <stdio.h>. + [_MALLOC_INTERNAL]: Move config.h, limits.h, and mem* to front of file. + (NULL): Move after stddef.h. + + * malloc/valloc.c: Don't include config.h; malloc.h already did. + + * malloc/malloc.c: Undo rms's change. + + * malloc/mcheck.c, malloc/malloc.h: Undo rms's change. + +Sat May 29 13:04:38 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * malloc/malloc.c (malloc) [emacs]: If size is 0, make it 1. + + * malloc/malloc.h (CONST): Define this always, + rather than `const' sometimes. + (memory_warnings): Use CONST, not __const, in decl. + * malloc/mcheck.c (checkhdr): Use CONST, not const. + +Fri May 14 19:34:54 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/Makefile: Remove depend-malloc dependency on malloc/gmalloc.c. + +Wed May 12 19:43:37 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * malloc/cfree.c: Put malloc.h include in _MALLOC_INTERNAL conditional. + +Wed May 12 16:24:23 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/cfree.c: Include <malloc.h> instead of <stdlib.h>. + [_LIBC]: Use function_alias only under this conditional. + [! _LIBC] (cfree): Define a function that just calls free. + +Mon May 10 16:56:09 1993 Jim Blandy (jimb@geech.gnu.ai.mit.edu) + + * malloc/cfree.c: Put the meat of the file inside a "#if + defined(__GNU_LIBRARY__)" clause, so that gmalloc.c, which + incorporates this file, can be used outside of the C library. + +Sun May 9 16:57:43 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/Makefile (malloc-dist): Add ChangeLog and mem-limits.h. + (malloc/ChangeLog): New rule using Noah's changelog-extract. + (malloc.tar): Use o flag to tar to make compatible archives. + (gmalloc-routines): Add calloc, valloc, and cfree. + (dist-routines): Remove [cv]alloc from here. + (routines): Remove cfree from here. + +Fri Mar 26 14:53:30 1993 Michael John Haertel (mike@skinner.cs.uoregon.edu) + + * malloc/malloc.c (malloc): Start searching at _heapindex, not + MALLOC_SEARCH_START. + * malloc/malloc.h (MALLOC_SEARCH_START): Macro removed. + * malloc/realloc.c (realloc): When malloc returns NULL, handle the + case of the block we need to unfree (which was just freed) having + been coalesced with its neighbors. + +Thu Mar 25 13:40:17 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Rules (mostlyclean): Remove the .o files for $(tests) and $(others). + Remove $(objpfx)depend-$(subdir). + (clean): Remove $(extra-objs). + * Makefile (clean): Remove $(install-lib) from $(objdir). + Don't try to remove ansi/ and trad/ or dist.tar or lint.out. + Remove $(objpfx)depend-. + * time/Makefile (extra-objs): Define new var. + * malloc/Makefile (extra-objs): Likewise. + +Wed Mar 24 16:09:26 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/Makefile (malloc/%.c, malloc/%.h): Rules removed. + +Mon Mar 22 15:35:54 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/malloc.h [_MALLOC_INTERNAL] + [__GNU_LIBRARY__ || STDC_HEADERS || USG] (memmove): Define in + terms of bcopy. + * malloc/malloc/gmalloc-head.c: Redo previously undone change. + +Thu Mar 18 04:59:21 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * malloc/malloc/gmalloc-head.c: Undo previous change. + +Tue Mar 9 11:32:35 1993 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * malloc/malloc/gmalloc-head.c: Remove #definitions of memset, + memcpy, and memmove; this is taken care of by malloc.h anyway. + +Thu Feb 25 14:49:52 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/malloc.h [_MALLOC_INTERNAL]: Move #include <stdio.h> to + front of file; it needs to come before size_t/ptrdiff_t frobnication. + +Mon Feb 22 12:19:19 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/dist-Makefile (gmalloc.c): Depend on Makefile. + + * malloc/Makefile (gmalloc-routines): New variable. + (dist-routines): Use it. + (malloc/Makefile): Also replace <GMALLOC-SOURCES> with + $(gmalloc-routines). + (malloc/Makefile): Make it unwritable to avoid accidental lossage. + Depend on Makefile. + + * malloc/dist-Makefile (gmalloc): New variable: <GMALLOC-SOURCES>. + (gmalloc.c): Use $(gmalloc), not $(sources). + Make the file unwritable to avoid accidental lossage. + + * malloc/mtrace.c: Don't #include <stdio.h> because <malloc.h> did + it for us. + + * malloc/valloc.c [! __GNU_LIBRARY__]: Replace hairy conditionals + with #include "getpagesize.h". + * malloc/Makefile (distribute, malloc-dist): Add getpagesize.h. + +Thu Feb 18 14:34:00 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/mcheck.c (checkhdr): Use `const', not `__const'. + +Tue Dec 29 18:18:58 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/Makefile (dist-headers): Define to malloc.h. + (headers): Replace malloc.h with $(dist-headers). + (malloc/Makefile): Use $(dist-headers) in place of $(headers). + (malloc-dist, distribute): Replace ChangeLog with OChangeLog. + + * malloc/dist-Makefile (malloc.tar{,.Z}): Depend on FORCE. + (FORCE): Define empty target. + +Tue Oct 27 18:11:19 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/mcheck.c (mcheck): Set abortfunc to either FUNC or abort; + never leave it unchanged. + Return 0 if mcheck_used; -1 if not. + * malloc/malloc.h (mcheck): Change return type in decl. + +Thu Oct 15 19:25:46 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/malloc.h (__after_morecore_hook): Declare new var. + * malloc/malloc.c (__after_morecore_hook): Define it. + (align): Call it. + +Mon Oct 12 15:56:07 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/malloc.h (r_alloc, r_alloc_free, r_re_alloc): Declare. + + * malloc/Makefile (dist-routines): Add ralloc. + (gpl2lgpl): Add ralloc.c. + +Mon Oct 12 13:37:16 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/malloc.h: Declare memory_warnings. + * malloc/Makefile (dist-routines): Add vm-limit. + (distribute): Add mem-limits.h. + (gpl2lgpl): Add vm-limit.c, mem-limits.h. + +Thu Aug 27 15:58:13 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * malloc/malloc.h [! __STDC__] (ptrdiff_t): #define. + +Wed Aug 26 18:15:47 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/free.c (__free): Rename to _free_internal. + (free), malloc/malloc.c (morecore): Change callers. + * malloc/malloc.h: Change decl. + +Tue Aug 18 17:38:13 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/Makefile (obstack.%): Remove rule. + (gpl2lgpl): Define this instead. + * posix/Makefile (gpl2lgpl): Define to include getopt source files. + * Makerules ($(gpl2lgpl)): New rule to snarf code and frob its + copying notices. + +Tue Jul 7 03:11:23 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/Makefile (dist-routines): Define with routines for malloc.tar. + (routines): Define with that plus the rest. + (nodist): Remove. + (routines): Add obstack. + (headers): Add obstack.h. + (obstack.%): New rule. + +Thu Jun 25 21:01:40 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * sysdeps/unix/morecore.c (__default_morecore): Deansideclized. + * malloc/*.c: Only #include <malloc.h> #ifndef _MALLOC_INTERNAL. + +Thu Jun 4 16:41:56 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/malloc.h (mtrace): Declare. + + * malloc/malloc.h, malloc/calloc.c, malloc/free.c, malloc/malloc.c, + malloc/mcheck.c, malloc/memalign.c, malloc/mstats.c, + malloc/mtrace.c, malloc/realloc.c, malloc/valloc.c: Deansideclized; + changed copyright notices to be independent of libc. + * malloc/Makefile (glob/%.c, glob/%.h): Don't need to ansideclificate. + +Fri May 22 01:52:04 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * assert/assert.h, ctype/ctype.h, dirent/dirent.h, grp/grp.h, + locale/locale.h, locale/localeinfo.h, math/math.h, + misc/sys/file.h, misc/sys/ioctl.h, misc/sys/ptrace.h, + misc/sys/uio.h, misc/sgtty.h, misc/nlist.h, posix/gnu/types.h, + posix/sys/wait.h, posix/sys/types.h, posix/sys/times.h, + posix/sys/utsname.h, posix/unistd.h, posix/tar.h, posix/utime.h, + posix/wordexp.h, posix/glob.h, posix/fnmatch.h, pwd/pwd.h, + resource/sys/resource.h, resource/sys/vlimit.h, + resource/sys/vtimes.h, setjmp/setjmp.h, signal/signal.h, + signal/gnu/signal.h, socket/sys/socket.h, stdio/stdio.h, + stdio/printf.h, stdlib/alloca.h, stdlib/stdlib.h, string/string.h, + termios/termios.h, time/sys/time.h, time/time.h, io/sys/stat.h, + io/fcntl.h, errno.h, stddef.h, malloc/malloc.h: + Deansideclized. Use <sys/cdefs.h> macros instead of ansidecl and + C++ cruft. + * features.h: #include <sys/cdefs.h>. + +Sun May 17 15:50:00 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) + + * malloc/mtrace.c (old_{free,malloc,realloc}_hook): Renamed to tr_& + to not conflict with mcheck.c when combined into gmalloc.c. + +Tue Apr 28 19:25:21 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) + + * malloc/valloc.c [emacs]: #include "config.h" + +Thu Apr 23 13:55:34 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) + + * malloc/realloc.c, malloc/malloc.c: Don't #define memcpy or memset + if already #define'd. + +Tue Apr 21 04:16:56 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * malloc/Makefile: Moved include ../Rules after malloc.tar rules. + They need $(routines), which Rules clears. + + * malloc/realloc.c (MIN): Renamed to min. Conflicted with HPUX + system header files. + +Tue Mar 17 17:31:06 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * malloc/dist-README: Changed mailing list addr to bug-glibc. + +Sun Mar 15 00:01:05 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) + + * malloc/Makefile (malloc/gmalloc.c): Depend on headers and sources. + +Fri Mar 13 17:20:19 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * malloc/Makefile (libmcheck.a), Makefile (crt0.o): Remove target + first; don't use -f to ln. + +Tue Feb 25 01:42:16 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * malloc/dist-README: Fixed mailing list addr. + +Mon Feb 17 05:04:00 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * malloc/Makefile (distribute): Add mcheck-init.c. + +Fri Feb 14 01:52:12 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * Makeconfig: Added comments describing objdir/Makeconfig and + editting Makeconfig. + (prefix, libdir, INSTALL, INSTALL_DATA): New variables for installing. + * Makerules (install): New target. + * Makefile (+subdir_targets): Add subdir_install. + (install): Depend on subdir_install. + (install-lib): Define variable to install libc.a and crt0.o. + * misc/Makefile (install-lib): Install bsd-compat. + * malloc/Makefile (install-lib): Install mcheck-init. + +Wed Feb 12 12:12:12 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) + + * malloc/mtrace.c: Use %p fmt for pointers. + + +Find older changes in OChangeLog. diff --git a/gnu/lib/libmalloc/Makefile b/gnu/lib/libmalloc/Makefile new file mode 100644 index 00000000000..6ff84a85755 --- /dev/null +++ b/gnu/lib/libmalloc/Makefile @@ -0,0 +1,13 @@ +# $Id: Makefile,v 1.1 1995/10/18 08:38:20 deraadt Exp $ + +CFLAGS+= -I${.CURDIR} + +LIB= gnumalloc +SRCS+= combined.c +#SRCS+= malloc.c free.c realloc.c +SRCS+= cfree.c calloc.c morecore.c +SRCS+= memalign.c valloc.c mcheck.c mtrace.c mstats.c vm-limit.c +SRCS+= ralloc.c +NOMAN= noman + +.include <bsd.lib.mk> diff --git a/gnu/lib/libmalloc/Makefile.gnu b/gnu/lib/libmalloc/Makefile.gnu new file mode 100644 index 00000000000..ec35f74dcbb --- /dev/null +++ b/gnu/lib/libmalloc/Makefile.gnu @@ -0,0 +1,57 @@ +# Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. + +# The GNU C Library 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 +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If +# not, write to the Free Software Foundation, Inc., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +# Makefile for standalone distribution of malloc. + +# Use this on System V. +#CPPFLAGS = -DUSG + +.PHONY: all +all: libmalloc.a gmalloc.o + +gmalloc = malloc.c free.c cfree.c realloc.c calloc.c morecore.c memalign.c valloc.c +sources = malloc.c free.c cfree.c realloc.c calloc.c morecore.c memalign.c valloc.c mcheck.c mtrace.c mstats.c vm-limit.c ralloc.c +objects = malloc.o free.o cfree.o realloc.o calloc.o morecore.o memalign.o valloc.o mcheck.o mtrace.o mstats.o vm-limit.o ralloc.o +headers = malloc.h + +libmalloc.a: $(objects) + ar crv $@ $(objects) + ranlib $@ + +$(objects): $(headers) + +gmalloc.c: gmalloc-head.c $(headers) $(gmalloc) Makefile + cat gmalloc-head.c $(headers) $(gmalloc) > $@-tmp + mv -f $@-tmp $@ +# Make it unwritable to avoid accidentally changing the file, +# since it is generated and any changes would be lost. + chmod a-w $@ + +.c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -I. -c $< $(OUTPUT_OPTION) + +.PHONY: clean realclean malloc-clean malloc-realclean +clean malloc-clean: + -rm -f libmalloc.a *.o core +realclean malloc-realclean: clean + -rm -f TAGS tags *~ + +# For inside the C library. +malloc.tar malloc.tar.Z: FORCE + $(MAKE) -C .. $@ +FORCE: diff --git a/gnu/lib/libmalloc/OChangeLog b/gnu/lib/libmalloc/OChangeLog new file mode 100644 index 00000000000..452aa53b323 --- /dev/null +++ b/gnu/lib/libmalloc/OChangeLog @@ -0,0 +1,34 @@ + **** All newer entries are in the C library ChangeLog file. **** + +Thu Jul 11 18:15:04 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Merged with C library version, which now has its own subdir. + * malloc.h, *.c: Use ansideclisms and #ifdefs for portability both + in and out of the C library. + * Makefile: New makefile for malloc subdir in libc. + Has targets to create malloc.tar{,.Z} by ansidecl processing on srcs. + * malloc/Makefile: New file; Makefile for standalone distribution. + * malloc/README: New file; info for same. + +Fri Apr 6 00:18:36 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) + + * Makefile: Add comments. + +Thu Apr 5 23:08:14 1990 Mike Haertel (mike at albert.ai.mit.edu) + + * mcheck.c (mcheck, checkhdr): Support user-supplied abort() + function. + * malloc.h: Declare __free(). + * Makefile: New target libmalloc.a. + +Thu Apr 5 21:56:03 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) + + * free.c (free): Split into free and __free. + * malloc.c (morecore): Call __free on oldinfo. + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 76 +version-control: never +End: diff --git a/gnu/lib/libmalloc/README b/gnu/lib/libmalloc/README new file mode 100644 index 00000000000..b5655c92820 --- /dev/null +++ b/gnu/lib/libmalloc/README @@ -0,0 +1,12 @@ +This is the standalone distribution of GNU malloc. +GNU malloc is part of the GNU C Library, but is also distributed separately. + +If you find bugs in GNU malloc, send reports to bug-glibc@prep.ai.mit.edu. + +GNU malloc is free software. See the file COPYING.LIB for copying conditions. + +The makefile builds libmalloc.a and gmalloc.o. If you are using GNU malloc +to replace your system's existing malloc package, it is important to make +sure you get all GNU functions, not some of the GNU functions and some from +the system library. gmalloc.o has all the functions in one file, so using +that will make sure you don't accidentally mix the two malloc packages. diff --git a/gnu/lib/libmalloc/VERSION b/gnu/lib/libmalloc/VERSION new file mode 100644 index 00000000000..c07e0806aac --- /dev/null +++ b/gnu/lib/libmalloc/VERSION @@ -0,0 +1,2 @@ +this version of GNU malloc was obtained from prep.ai.mit.edu on +9/22/1993. There was no version noted. diff --git a/gnu/lib/libmalloc/calloc.c b/gnu/lib/libmalloc/calloc.c new file mode 100644 index 00000000000..f870e944806 --- /dev/null +++ b/gnu/lib/libmalloc/calloc.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* Allocate an array of NMEMB elements each SIZE bytes long. + The entire array is initialized to zeros. */ +__ptr_t +calloc (nmemb, size) + register size_t nmemb; + register size_t size; +{ + register __ptr_t result = malloc (nmemb * size); + + if (result != NULL) + (void) memset (result, 0, nmemb * size); + + return result; +} diff --git a/gnu/lib/libmalloc/cfree.c b/gnu/lib/libmalloc/cfree.c new file mode 100644 index 00000000000..adc1ff698e0 --- /dev/null +++ b/gnu/lib/libmalloc/cfree.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#undef cfree + +#ifdef _LIBC + +#include <ansidecl.h> +#include <gnu-stabs.h> + +function_alias(cfree, free, void, (ptr), + DEFUN(cfree, (ptr), PTR ptr)) + +#else + +void +cfree (ptr) + __ptr_t ptr; +{ + free (ptr); +} + +#endif diff --git a/gnu/lib/libmalloc/combined.c b/gnu/lib/libmalloc/combined.c new file mode 100644 index 00000000000..bfb7880d6d9 --- /dev/null +++ b/gnu/lib/libmalloc/combined.c @@ -0,0 +1,12 @@ +/* + * this file (combined.c) is malloc.c, free.c, and realloc.c, combined into + * one file, because the malloc.o in libc defined malloc, realloc, and free, + * and libc sometimes invokes realloc, which can greatly confuse things + * in the linking process... + * + * $Id: combined.c,v 1.1 1995/10/18 08:38:21 deraadt Exp $ + */ + +#include "malloc.c" +#include "free.c" +#include "realloc.c" diff --git a/gnu/lib/libmalloc/free.c b/gnu/lib/libmalloc/free.c new file mode 100644 index 00000000000..7d2a77c8a2f --- /dev/null +++ b/gnu/lib/libmalloc/free.c @@ -0,0 +1,210 @@ +/* Free a block of memory allocated by `malloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* Debugging hook for free. */ +void (*__free_hook) __P ((__ptr_t __ptr)); + +/* List of blocks allocated by memalign. */ +struct alignlist *_aligned_blocks = NULL; + +/* Return memory to the heap. + Like `free' but don't call a __free_hook if there is one. */ +void +_free_internal (ptr) + __ptr_t ptr; +{ + int type; + size_t block, blocks; + register size_t i; + struct list *prev, *next; + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Get as many statistics as early as we can. */ + --_chunks_used; + _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; + _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = _heapindex; + if (i > block) + while (i > block) + i = _heapinfo[i].free.prev; + else + { + do + i = _heapinfo[i].free.next; + while (i > 0 && i < block); + i = _heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + _heapinfo[i].free.size) + { + /* Coalesce this block with its predecessor. */ + _heapinfo[i].free.size += _heapinfo[block].busy.info.size; + block = i; + } + else + { + /* Really link this block back into the free list. */ + _heapinfo[block].free.size = _heapinfo[block].busy.info.size; + _heapinfo[block].free.next = _heapinfo[i].free.next; + _heapinfo[block].free.prev = i; + _heapinfo[i].free.next = block; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + ++_chunks_free; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) + { + _heapinfo[block].free.size + += _heapinfo[_heapinfo[block].free.next].free.size; + _heapinfo[block].free.next + = _heapinfo[_heapinfo[block].free.next].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + --_chunks_free; + } + + /* Now see if we can return stuff to the system. */ + blocks = _heapinfo[block].free.size; + if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit + && (*__morecore) (0) == ADDRESS (block + blocks)) + { + register size_t bytes = blocks * BLOCKSIZE; + _heaplimit -= blocks; + (*__morecore) (-bytes); + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[block].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + block = _heapinfo[block].free.prev; + --_chunks_free; + _bytes_free -= bytes; + } + + /* Set the next search to begin at this block. */ + _heapindex = block; + break; + + default: + /* Do some of the statistics. */ + --_chunks_used; + _bytes_used -= 1 << type; + ++_chunks_free; + _bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) ((char *) ADDRESS (block) + + (_heapinfo[block].busy.info.frag.first << type)); + + if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ + next = prev; + for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) + next = next->next; + prev->prev->next = next; + if (next != NULL) + next->prev = prev->prev; + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + ++_chunks_used; + _bytes_used += BLOCKSIZE; + _chunks_free -= BLOCKSIZE >> type; + _bytes_free -= BLOCKSIZE; + + free (ADDRESS (block)); + } + else if (_heapinfo[block].busy.info.frag.nfree != 0) + { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next->next = prev->next; + next->prev = prev; + prev->next = next; + if (next->next != NULL) + next->next->prev = next; + ++_heapinfo[block].busy.info.frag.nfree; + } + else + { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + _heapinfo[block].busy.info.frag.nfree = 1; + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) ptr - (char *) NULL) + % BLOCKSIZE >> type); + prev->next = _fraghead[type].next; + prev->prev = &_fraghead[type]; + prev->prev->next = prev; + if (prev->next != NULL) + prev->next->prev = prev; + } + break; + } +} + +/* Return memory to the heap. */ +void +free (ptr) + __ptr_t ptr; +{ + register struct alignlist *l; + + if (ptr == NULL) + return; + + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == ptr) + { + l->aligned = NULL; /* Mark the slot in the list as free. */ + ptr = l->exact; + break; + } + + if (__free_hook != NULL) + (*__free_hook) (ptr); + else + _free_internal (ptr); +} diff --git a/gnu/lib/libmalloc/getpagesize.h b/gnu/lib/libmalloc/getpagesize.h new file mode 100644 index 00000000000..22b71726501 --- /dev/null +++ b/gnu/lib/libmalloc/getpagesize.h @@ -0,0 +1,39 @@ +#include <sys/param.h> +#ifdef BSD +#ifndef BSD4_1 +#define HAVE_GETPAGESIZE +#endif +#endif + +#ifndef HAVE_GETPAGESIZE + +#ifdef VMS +#define getpagesize() 512 +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef _SC_PAGESIZE +#define getpagesize() sysconf(_SC_PAGESIZE) +#else + +#include <sys/param.h> + +#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 */ +#define getpagesize() NBPC +#endif /* no NBPG */ +#endif /* no EXEC_PAGESIZE */ +#endif /* no _SC_PAGESIZE */ + +#endif /* not HAVE_GETPAGESIZE */ + diff --git a/gnu/lib/libmalloc/gmalloc-head.c b/gnu/lib/libmalloc/gmalloc-head.c new file mode 100644 index 00000000000..e5f82c3e0d1 --- /dev/null +++ b/gnu/lib/libmalloc/gmalloc-head.c @@ -0,0 +1,6 @@ +/* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ + +#define _MALLOC_INTERNAL + +/* The malloc headers and source files from the C library follow here. */ + diff --git a/gnu/lib/libmalloc/malloc.c b/gnu/lib/libmalloc/malloc.c new file mode 100644 index 00000000000..47a6b8d46e5 --- /dev/null +++ b/gnu/lib/libmalloc/malloc.c @@ -0,0 +1,318 @@ +/* Memory allocator `malloc'. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* How to really get more memory. */ +__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; + +/* Debugging hook for `malloc'. */ +__ptr_t (*__malloc_hook) __P ((size_t __size)); + +/* Pointer to the base of the first block. */ +char *_heapbase; + +/* Block information table. Allocated with align/__free (not malloc/free). */ +malloc_info *_heapinfo; + +/* Number of info entries. */ +static size_t heapsize; + +/* Search index in the info table. */ +size_t _heapindex; + +/* Limit of valid info table indices. */ +size_t _heaplimit; + +/* Free lists for each fragment size. */ +struct list _fraghead[BLOCKLOG]; + +/* Instrumentation. */ +size_t _chunks_used; +size_t _bytes_used; +size_t _chunks_free; +size_t _bytes_free; + +/* Are you experienced? */ +int __malloc_initialized; + +void (*__after_morecore_hook) __P ((void)); + +/* Aligned allocation. */ +static __ptr_t align __P ((size_t)); +static __ptr_t +align (size) + size_t size; +{ + __ptr_t result; + unsigned long int adj; + + result = (*__morecore) (size); + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % BLOCKSIZE; + if (adj != 0) + { + adj = BLOCKSIZE - adj; + (void) (*__morecore) (adj); + result = (char *) result + adj; + } + + if (__after_morecore_hook) + (*__after_morecore_hook) (); + + return result; +} + +/* Set everything up and remember that we have. */ +static int initialize __P ((void)); +static int +initialize () +{ + heapsize = HEAP / BLOCKSIZE; + _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); + if (_heapinfo == NULL) + return 0; + memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); + _heapinfo[0].free.size = 0; + _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; + _heapindex = 0; + _heapbase = (char *) _heapinfo; + __malloc_initialized = 1; + return 1; +} + +/* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ +static __ptr_t morecore __P ((size_t)); +static __ptr_t +morecore (size) + size_t size; +{ + __ptr_t result; + malloc_info *newinfo, *oldinfo; + size_t newsize; + + result = align (size); + if (result == NULL) + return NULL; + + /* Check if we need to grow the info table. */ + if ((size_t) BLOCK ((char *) result + size) > heapsize) + { + newsize = heapsize; + while ((size_t) BLOCK ((char *) result + size) > newsize) + newsize *= 2; + newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); + if (newinfo == NULL) + { + (*__morecore) (-size); + return NULL; + } + memset (newinfo, 0, newsize * sizeof (malloc_info)); + memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); + oldinfo = _heapinfo; + newinfo[BLOCK (oldinfo)].busy.type = 0; + newinfo[BLOCK (oldinfo)].busy.info.size + = BLOCKIFY (heapsize * sizeof (malloc_info)); + _heapinfo = newinfo; + _free_internal (oldinfo); + heapsize = newsize; + } + + _heaplimit = BLOCK ((char *) result + size); + return result; +} + +/* Allocate memory from the heap. */ +__ptr_t +malloc (size) + size_t size; +{ + __ptr_t result; + size_t block, blocks, lastblocks, start; + register size_t i; + struct list *next; + + /* ANSI C allows `malloc (0)' to either return NULL, or to return a + valid address you can realloc and free (though not dereference). + + It turns out that some extant code (sunrpc, at least Ultrix's version) + expects `malloc (0)' to return non-NULL and breaks otherwise. + Be compatible. */ + +#if 0 + if (size == 0) + return NULL; +#endif + + if (__malloc_hook != NULL) + return (*__malloc_hook) (size); + + if (!__malloc_initialized) + if (!initialize ()) + return NULL; + + if (size < sizeof (struct list)) + size = sizeof (struct list); + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) + { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + register size_t log = 1; + --size; + while ((size /= 2) != 0) + ++log; + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = _fraghead[log].next; + if (next != NULL) + { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (__ptr_t) next; + next->prev->next = next->next; + if (next->next != NULL) + next->next->prev = next->prev; + block = BLOCK (result); + if (--_heapinfo[block].busy.info.frag.nfree != 0) + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) next->next - (char *) NULL) + % BLOCKSIZE) >> log; + + /* Update the statistics. */ + ++_chunks_used; + _bytes_used += 1 << log; + --_chunks_free; + _bytes_free -= 1 << log; + } + else + { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = malloc (BLOCKSIZE); + if (result == NULL) + return NULL; + + /* Link all fragments but the first into the free list. */ + for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) + { + next = (struct list *) ((char *) result + (i << log)); + next->next = _fraghead[log].next; + next->prev = &_fraghead[log]; + next->prev->next = next; + if (next->next != NULL) + next->next->prev = next; + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + _heapinfo[block].busy.type = log; + _heapinfo[block].busy.info.frag.nfree = i - 1; + _heapinfo[block].busy.info.frag.first = i - 1; + + _chunks_free += (BLOCKSIZE >> log) - 1; + _bytes_free += BLOCKSIZE - (1 << log); + _bytes_used -= BLOCKSIZE - (1 << log); + } + } + else + { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY (size); + start = block = _heapindex; + while (_heapinfo[block].free.size < blocks) + { + block = _heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Check to see if + the new core will be contiguous with the final free + block; if so we don't need to get as much. */ + block = _heapinfo[0].free.prev; + lastblocks = _heapinfo[block].free.size; + if (_heaplimit != 0 && block + lastblocks == _heaplimit && + (*__morecore) (0) == ADDRESS (block + lastblocks) && + (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL) + { + _heapinfo[block].free.size = blocks; + _bytes_free += (blocks - lastblocks) * BLOCKSIZE; + continue; + } + result = morecore (blocks * BLOCKSIZE); + if (result == NULL) + return NULL; + block = BLOCK (result); + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + return result; + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS (block); + if (_heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + _heapinfo[block + blocks].free.size + = _heapinfo[block].free.size - blocks; + _heapinfo[block + blocks].free.next + = _heapinfo[block].free.next; + _heapinfo[block + blocks].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[_heapinfo[block].free.next].free.prev + = _heapindex = block + blocks; + } + else + { + /* The block exactly matches our requirements, + so just remove it from the list. */ + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapindex = _heapinfo[block].free.next; + --_chunks_free; + } + + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + _bytes_free -= blocks * BLOCKSIZE; + } + + return result; +} diff --git a/gnu/lib/libmalloc/malloc.h b/gnu/lib/libmalloc/malloc.h new file mode 100644 index 00000000000..94b89eec732 --- /dev/null +++ b/gnu/lib/libmalloc/malloc.h @@ -0,0 +1,265 @@ +/* Declarations for `malloc' and friends. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_H + +#define _MALLOC_H 1 + +#ifdef _MALLOC_INTERNAL + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) +#include <string.h> +#else +#ifndef memset +#define memset(s, zero, n) bzero ((s), (n)) +#endif +#ifndef memcpy +#define memcpy(d, s, n) bcopy ((s), (d), (n)) +#endif +#ifndef memmove +#define memmove(d, s, n) bcopy ((s), (d), (n)) +#endif +#endif + +#if defined(__GNU_LIBRARY__) || defined(__STDC__) +#include <limits.h> +#else +#define CHAR_BIT 8 +#endif + +#endif /* _MALLOC_INTERNAL. */ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#ifndef __NetBSD__ +#undef __P +#define __P(args) args +#else +#include <sys/cdefs.h> +#endif +#undef __ptr_t +#define __ptr_t void * +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(args) () +#undef const +#define const +#undef __ptr_t +#define __ptr_t char * +#endif /* C++ or ANSI C. */ + +#ifdef __STDC__ +#include <stddef.h> +#else +#undef size_t +#define size_t unsigned int +#undef ptrdiff_t +#define ptrdiff_t int +#endif + +#ifndef NULL +#define NULL 0 +#endif + + +/* Allocate SIZE bytes of memory. */ +extern __ptr_t malloc __P ((size_t __size)); +/* Re-allocate the previously allocated block + in __ptr_t, making the new block SIZE bytes long. */ +extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size)); +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern __ptr_t calloc __P ((size_t __nmemb, size_t __size)); +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free __P ((__ptr_t __ptr)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ +extern __ptr_t memalign __P ((size_t __alignment, size_t __size)); + +/* Allocate SIZE bytes on a page boundary. */ +extern __ptr_t valloc __P ((size_t __size)); + + +#ifdef _MALLOC_INTERNAL + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE (1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + +/* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ +#define HEAP (INT_BIT > 16 ? 4194304 : 65536) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ +#define FINAL_FREE_BLOCKS 8 + +/* Data structure giving per-block information. */ +typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + /* Heap information for a free block + (that may be the first of a free cluster). */ + struct + { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + +/* Pointer to first block of the heap. */ +extern char *_heapbase; + +/* Table indexed by block number giving per-block information. */ +extern malloc_info *_heapinfo; + +/* Address to block number and vice versa. */ +#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) + +/* Current search index for the heap table. */ +extern size_t _heapindex; + +/* Limit of valid info table indices. */ +extern size_t _heaplimit; + +/* Doubly linked lists of free fragments. */ +struct list + { + struct list *next; + struct list *prev; + }; + +/* Free list headers for each fragment size. */ +extern struct list _fraghead[]; + +/* List of blocks allocated with `memalign' (or `valloc'). */ +struct alignlist + { + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ + }; +extern struct alignlist *_aligned_blocks; + +/* Instrumentation. */ +extern size_t _chunks_used; +extern size_t _bytes_used; +extern size_t _chunks_free; +extern size_t _bytes_free; + +/* Internal version of `free' used in `morecore' (malloc.c). */ +extern void _free_internal __P ((__ptr_t __ptr)); + +#endif /* _MALLOC_INTERNAL. */ + +/* Underlying allocation function; successive calls should + return contiguous pieces of memory. */ +extern __ptr_t (*__morecore) __P ((ptrdiff_t __size)); + +/* Default value of `__morecore'. */ +extern __ptr_t __default_morecore __P ((ptrdiff_t __size)); + +/* If not NULL, this function is called after each time + `__morecore' is called to increase the data size. */ +extern void (*__after_morecore_hook) __P ((void)); + +/* Nonzero if `malloc' has been called and done its initialization. */ +extern int __malloc_initialized; + +/* Hooks for debugging versions. */ +extern void (*__free_hook) __P ((__ptr_t __ptr)); +extern __ptr_t (*__malloc_hook) __P ((size_t __size)); +extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); + +/* Activate a standard collection of debugging hooks. */ +extern int mcheck __P ((void (*__func) __P ((void)))); + +/* Activate a standard collection of tracing hooks. */ +extern void mtrace __P ((void)); + +/* Statistics available to the user. */ +struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + +/* Pick up the current statistics. */ +extern struct mstats mstats __P ((void)); + +/* Call WARNFUN with a warning message when memory usage is high. */ +extern void memory_warnings __P ((__ptr_t __start, + void (*__warnfun) __P ((__const char *)))); + + +/* Relocating allocator. */ + +/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ +extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size)); + +/* Free the storage allocated in HANDLEPTR. */ +extern void r_alloc_free __P ((__ptr_t *__handleptr)); + +/* Adjust the block at HANDLEPTR to be SIZE bytes long. */ +extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size)); + + +#ifdef __cplusplus +} +#endif + +#endif /* malloc.h */ diff --git a/gnu/lib/libmalloc/mcheck.c b/gnu/lib/libmalloc/mcheck.c new file mode 100644 index 00000000000..f7d9d4f892e --- /dev/null +++ b/gnu/lib/libmalloc/mcheck.c @@ -0,0 +1,133 @@ +/* Standard debugging hooks for `malloc'. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +/* Old hook values. */ +static void (*old_free_hook) __P ((__ptr_t ptr)); +static __ptr_t (*old_malloc_hook) __P ((size_t size)); +static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, size_t size)); + +/* Function to call when something awful happens. */ +static void (*abortfunc) __P ((void)); + +/* Arbitrary magical numbers. */ +#define MAGICWORD 0xfedabeeb +#define MAGICBYTE ((char) 0xd7) + +struct hdr + { + size_t size; /* Exact size requested by user. */ + unsigned long int magic; /* Magic number to check header integrity. */ + }; + +static void checkhdr __P ((const struct hdr *)); +static void +checkhdr (hdr) + const struct hdr *hdr; +{ + if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE) + (*abortfunc) (); +} + +static void freehook __P ((__ptr_t)); +static void +freehook (ptr) + __ptr_t ptr; +{ + struct hdr *hdr = ((struct hdr *) ptr) - 1; + checkhdr (hdr); + hdr->magic = 0; + __free_hook = old_free_hook; + free (hdr); + __free_hook = freehook; +} + +static __ptr_t mallochook __P ((size_t)); +static __ptr_t +mallochook (size) + size_t size; +{ + struct hdr *hdr; + + __malloc_hook = old_malloc_hook; + hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1); + __malloc_hook = mallochook; + if (hdr == NULL) + return NULL; + + hdr->size = size; + hdr->magic = MAGICWORD; + ((char *) &hdr[1])[size] = MAGICBYTE; + return (__ptr_t) (hdr + 1); +} + +static __ptr_t reallochook __P ((__ptr_t, size_t)); +static __ptr_t +reallochook (ptr, size) + __ptr_t ptr; + size_t size; +{ + struct hdr *hdr = ((struct hdr *) ptr) - 1; + + checkhdr (hdr); + __free_hook = old_free_hook; + __malloc_hook = old_malloc_hook; + __realloc_hook = old_realloc_hook; + hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1); + __free_hook = freehook; + __malloc_hook = mallochook; + __realloc_hook = reallochook; + if (hdr == NULL) + return NULL; + + hdr->size = size; + ((char *) &hdr[1])[size] = MAGICBYTE; + return (__ptr_t) (hdr + 1); +} + +int +mcheck (func) + void (*func) __P ((void)); +{ + extern void abort __P ((void)); + static int mcheck_used = 0; + + abortfunc = (func != NULL) ? func : abort; + + /* These hooks may not be safely inserted if malloc is already in use. */ + if (!__malloc_initialized && !mcheck_used) + { + old_free_hook = __free_hook; + __free_hook = freehook; + old_malloc_hook = __malloc_hook; + __malloc_hook = mallochook; + old_realloc_hook = __realloc_hook; + __realloc_hook = reallochook; + mcheck_used = 1; + } + + return mcheck_used ? 0 : -1; +} diff --git a/gnu/lib/libmalloc/mem-limits.h b/gnu/lib/libmalloc/mem-limits.h new file mode 100644 index 00000000000..ab594fcf3cc --- /dev/null +++ b/gnu/lib/libmalloc/mem-limits.h @@ -0,0 +1,132 @@ +/* Includes for memory limit warnings. + Copyright (C) 1990, 1993 Free Software Foundation, Inc. + + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#if defined(__osf__) && (defined(__mips) || defined(mips)) +#include <sys/time.h> +#include <sys/resource.h> +#endif + +#ifdef __bsdi__ +#define BSD4_2 +#endif + +#ifndef BSD4_2 +#ifndef USG +#include <sys/vlimit.h> +#endif /* not USG */ +#else /* if BSD4_2 */ +#include <sys/time.h> +#include <sys/resource.h> +#endif /* BSD4_2 */ + +#ifdef emacs +/* The important properties of this type are that 1) it's a pointer, and + 2) arithmetic on it should work as if the size of the object pointed + to has a size of 1. */ +#ifdef __STDC__ +typedef void *POINTER; +#else +typedef char *POINTER; +#endif + +typedef unsigned long SIZE; + +#ifdef NULL +#undef NULL +#endif +#define NULL ((POINTER) 0) + +extern POINTER start_of_data (); +#ifdef DATA_SEG_BITS +#define EXCEEDS_LISP_PTR(ptr) \ + (((unsigned int) (ptr) & ~DATA_SEG_BITS) >> VALBITS) +#else +#define EXCEEDS_LISP_PTR(ptr) ((unsigned int) (ptr) >> VALBITS) +#endif + +#ifdef BSD +#ifndef DATA_SEG_BITS +extern char etext; +#define start_of_data() &etext +#endif +#endif + +#else /* Not emacs */ +extern char etext; +#define start_of_data() &etext +#endif /* Not emacs */ + + + +/* start of data space; can be changed by calling malloc_init */ +static POINTER data_space_start; + +/* Number of bytes of writable memory we can expect to be able to get */ +static unsigned int lim_data; + +#ifdef USG + +static void +get_lim_data () +{ + extern long ulimit (); + + lim_data = -1; + + /* Use the ulimit call, if we seem to have it. */ +#if !defined (ULIMIT_BREAK_VALUE) || defined (LINUX) + lim_data = ulimit (3, 0); +#endif + + /* If that didn't work, just use the macro's value. */ +#ifdef ULIMIT_BREAK_VALUE + if (lim_data == -1) + lim_data = ULIMIT_BREAK_VALUE; +#endif + + lim_data -= (long) data_space_start; +} + +#else /* not USG */ +#if !defined(BSD4_2) && !defined(__osf__) + +static void +get_lim_data () +{ + lim_data = vlimit (LIM_DATA, -1); +} + +#else /* BSD4_2 */ + +static void +get_lim_data () +{ + struct rlimit XXrlimit; + + getrlimit (RLIMIT_DATA, &XXrlimit); +#ifdef RLIM_INFINITY + lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ +#else + lim_data = XXrlimit.rlim_cur; /* soft limit */ +#endif +} +#endif /* BSD4_2 */ +#endif /* not USG */ diff --git a/gnu/lib/libmalloc/memalign.c b/gnu/lib/libmalloc/memalign.c new file mode 100644 index 00000000000..f5ad17cb23a --- /dev/null +++ b/gnu/lib/libmalloc/memalign.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +__ptr_t +memalign (alignment, size) + size_t alignment; + size_t size; +{ + __ptr_t result; + unsigned long int adj; + + size = ((size + alignment - 1) / alignment) * alignment; + + result = malloc (size); + if (result == NULL) + return NULL; + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % alignment; + if (adj != 0) + { + struct alignlist *l; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) + { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) + { + free (result); + return NULL; + } + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + l->next = _aligned_blocks; + _aligned_blocks = l; + } + + return result; +} diff --git a/gnu/lib/libmalloc/morecore.c b/gnu/lib/libmalloc/morecore.c new file mode 100644 index 00000000000..c9a9ca5aaa6 --- /dev/null +++ b/gnu/lib/libmalloc/morecore.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#ifndef __GNU_LIBRARY__ +#define __sbrk sbrk +#endif + +extern __ptr_t __sbrk __P ((int increment)); + +#ifndef NULL +#define NULL 0 +#endif + +/* Allocate INCREMENT more bytes of data space, + and return the start of data space, or NULL on errors. + If INCREMENT is negative, shrink data space. */ +__ptr_t +__default_morecore (increment) + ptrdiff_t increment; +{ + __ptr_t result = __sbrk ((int) increment); + if (result == (__ptr_t) -1) + return NULL; + return result; +} diff --git a/gnu/lib/libmalloc/mstats.c b/gnu/lib/libmalloc/mstats.c new file mode 100644 index 00000000000..511cdad9878 --- /dev/null +++ b/gnu/lib/libmalloc/mstats.c @@ -0,0 +1,39 @@ +/* Access the statistics maintained by `malloc'. + Copyright 1990, 1991, 1992 Free Software Foundation + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +struct mstats +mstats () +{ + struct mstats result; + + result.bytes_total = (char *) (*__morecore) (0) - _heapbase; + result.chunks_used = _chunks_used; + result.bytes_used = _bytes_used; + result.chunks_free = _chunks_free; + result.bytes_free = _bytes_free; + return result; +} diff --git a/gnu/lib/libmalloc/mtrace.awk b/gnu/lib/libmalloc/mtrace.awk new file mode 100644 index 00000000000..d7689cec3ff --- /dev/null +++ b/gnu/lib/libmalloc/mtrace.awk @@ -0,0 +1,36 @@ +# +# Awk program to analyze mtrace.c output. +# +$1 == "+" { if (allocated[$2] != "") + print "+", $2, "Alloc", NR, "duplicate:", allocated[$2]; + else + allocated[$2] = $3; + } +$1 == "-" { if (allocated[$2] != "") { + allocated[$2] = ""; + if (allocated[$2] != "") + print "DELETE FAILED", $2, allocated[$2]; + } else + print "-", $2, "Free", NR, "was never alloc'd"; + } +$1 == "<" { if (allocated[$2] != "") + allocated[$2] = ""; + else + print "-", $2, "Realloc", NR, "was never alloc'd"; + } +$1 == ">" { if (allocated[$2] != "") + print "+", $2, "Realloc", NR, "duplicate:", allocated[$2]; + else + allocated[$2] = $3; + } + +# Ignore "= Start" +$1 == "=" { } +# Ignore failed realloc attempts for now +$1 == "!" { } + + +END { for (x in allocated) + if (allocated[x] != "") + print "+", x, allocated[x]; + } diff --git a/gnu/lib/libmalloc/mtrace.c b/gnu/lib/libmalloc/mtrace.c new file mode 100644 index 00000000000..5dae86aa808 --- /dev/null +++ b/gnu/lib/libmalloc/mtrace.c @@ -0,0 +1,150 @@ +/* More debugging hooks for `malloc'. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Written April 2, 1991 by John Gilmore of Cygnus Support. + Based on mcheck.c by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#include <stdio.h> + +#ifndef __GNU_LIBRARY__ +extern char *getenv (); +#else +#include <stdlib.h> +#endif + +static FILE *mallstream; +static char mallenv[]= "MALLOC_TRACE"; +static char mallbuf[BUFSIZ]; /* Buffer for the output. */ + +/* Address to breakpoint on accesses to... */ +__ptr_t mallwatch; + +/* Old hook values. */ +static void (*tr_old_free_hook) __P ((__ptr_t ptr)); +static __ptr_t (*tr_old_malloc_hook) __P ((size_t size)); +static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size)); + +/* This function is called when the block being alloc'd, realloc'd, or + freed has an address matching the variable "mallwatch". In a debugger, + set "mallwatch" to the address of interest, then put a breakpoint on + tr_break. */ + +void tr_break __P ((void)); +void +tr_break () +{ +} + +static void tr_freehook __P ((__ptr_t)); +static void +tr_freehook (ptr) + __ptr_t ptr; +{ + fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */ + if (ptr == mallwatch) + tr_break (); + __free_hook = tr_old_free_hook; + free (ptr); + __free_hook = tr_freehook; +} + +static __ptr_t tr_mallochook __P ((size_t)); +static __ptr_t +tr_mallochook (size) + size_t size; +{ + __ptr_t hdr; + + __malloc_hook = tr_old_malloc_hook; + hdr = (__ptr_t) malloc (size); + __malloc_hook = tr_mallochook; + + /* We could be printing a NULL here; that's OK. */ + fprintf (mallstream, "+ %p %x\n", hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return hdr; +} + +static __ptr_t tr_reallochook __P ((__ptr_t, size_t)); +static __ptr_t +tr_reallochook (ptr, size) + __ptr_t ptr; + size_t size; +{ + __ptr_t hdr; + + if (ptr == mallwatch) + tr_break (); + + __free_hook = tr_old_free_hook; + __malloc_hook = tr_old_malloc_hook; + __realloc_hook = tr_old_realloc_hook; + hdr = (__ptr_t) realloc (ptr, size); + __free_hook = tr_freehook; + __malloc_hook = tr_mallochook; + __realloc_hook = tr_reallochook; + if (hdr == NULL) + /* Failed realloc. */ + fprintf (mallstream, "! %p %x\n", ptr, size); + else + fprintf (mallstream, "< %p\n> %p %x\n", ptr, hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return hdr; +} + +/* We enable tracing if either the environment variable MALLOC_TRACE + is set, or if the variable mallwatch has been patched to an address + that the debugging user wants us to stop on. When patching mallwatch, + don't forget to set a breakpoint on tr_break! */ + +void +mtrace () +{ + char *mallfile; + + mallfile = getenv (mallenv); + if (mallfile != NULL || mallwatch != NULL) + { + mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w"); + if (mallstream != NULL) + { + /* Be sure it doesn't malloc its buffer! */ + setbuf (mallstream, mallbuf); + fprintf (mallstream, "= Start\n"); + tr_old_free_hook = __free_hook; + __free_hook = tr_freehook; + tr_old_malloc_hook = __malloc_hook; + __malloc_hook = tr_mallochook; + tr_old_realloc_hook = __realloc_hook; + __realloc_hook = tr_reallochook; + } + } +} diff --git a/gnu/lib/libmalloc/ralloc.c b/gnu/lib/libmalloc/ralloc.c new file mode 100644 index 00000000000..6eef29f7d4c --- /dev/null +++ b/gnu/lib/libmalloc/ralloc.c @@ -0,0 +1,514 @@ +/* Block-relocating memory allocator. + Copyright (C) 1993 Free Software Foundation, Inc. + + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* NOTES: + + Only relocate the blocs neccessary for SIZE in r_alloc_sbrk, + rather than all of them. This means allowing for a possible + hole between the first bloc and the end of malloc storage. */ + +#ifdef emacs + +#include "config.h" +#include "lisp.h" /* Needed for VALBITS. */ + +#undef NULL + +/* The important properties of this type are that 1) it's a pointer, and + 2) arithmetic on it should work as if the size of the object pointed + to has a size of 1. */ +#if 0 /* Arithmetic on void* is a GCC extension. */ +#ifdef __STDC__ +typedef void *POINTER; +#else + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +typedef char *POINTER; + +#endif +#endif /* 0 */ + +/* Unconditionally use char * for this. */ +typedef char *POINTER; + +typedef unsigned long SIZE; + +/* Declared in dispnew.c, this version doesn't screw up if regions + overlap. */ +extern void safe_bcopy (); + +#include "getpagesize.h" + +#else /* Not emacs. */ + +#include <stddef.h> + +typedef size_t SIZE; +typedef void *POINTER; + +#include <unistd.h> +#include <malloc.h> +#include <string.h> + +#define safe_bcopy(x, y, z) memmove (y, x, z) + +#endif /* emacs. */ + +#define NIL ((POINTER) 0) + +/* A flag to indicate whether we have initialized ralloc yet. For + Emacs's sake, please do not make this local to malloc_init; on some + machines, the dumping procedure makes all static variables + read-only. On these machines, the word static is #defined to be + the empty string, meaning that r_alloc_initialized becomes an + automatic variable, and loses its value each time Emacs is started up. */ +static int r_alloc_initialized = 0; + +static void r_alloc_init (); + +/* Declarations for working with the malloc, ralloc, and system breaks. */ + +/* Function to set the real break value. */ +static POINTER (*real_morecore) (); + +/* The break value, as seen by malloc (). */ +static POINTER virtual_break_value; + +/* The break value, viewed by the relocatable blocs. */ +static POINTER break_value; + +/* The REAL (i.e., page aligned) break value of the process. */ +static POINTER page_break_value; + +/* This is the size of a page. We round memory requests to this boundary. */ +static int page_size; + +/* Whenever we get memory from the system, get this many extra bytes. This + must be a multiple of page_size. */ +static int extra_bytes; + +/* Macros for rounding. Note that rounding to any value is possible + by changing the definition of PAGE. */ +#define PAGE (getpagesize ()) +#define ALIGNED(addr) (((unsigned long) (addr) & (page_size - 1)) == 0) +#define ROUNDUP(size) (((unsigned long) (size) + page_size - 1) & ~(page_size - 1)) +#define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1))) + +/* Functions to get and return memory from the system. */ + +/* Obtain SIZE bytes of space. If enough space is not presently available + in our process reserve, (i.e., (page_break_value - break_value)), + this means getting more page-aligned space from the system. + + Return non-zero if all went well, or zero if we couldn't allocate + the memory. */ +static int +obtain (size) + SIZE size; +{ + SIZE already_available = page_break_value - break_value; + + if (already_available < size) + { + SIZE get = ROUNDUP (size - already_available); + /* Get some extra, so we can come here less often. */ + get += extra_bytes; + + if ((*real_morecore) (get) == 0) + return 0; + + page_break_value += get; + } + + break_value += size; + + return 1; +} + +/* Obtain SIZE bytes of space and return a pointer to the new area. + If we could not allocate the space, return zero. */ + +static POINTER +get_more_space (size) + SIZE size; +{ + POINTER ptr = break_value; + if (obtain (size)) + return ptr; + else + return 0; +} + +/* Note that SIZE bytes of space have been relinquished by the process. + If SIZE is more than a page, return the space to the system. */ + +static void +relinquish (size) + SIZE size; +{ + POINTER new_page_break; + int excess; + + break_value -= size; + new_page_break = (POINTER) ROUNDUP (break_value); + excess = (char *) page_break_value - (char *) new_page_break; + + if (excess > extra_bytes * 2) + { + /* Keep extra_bytes worth of empty space. + And don't free anything unless we can free at least extra_bytes. */ + if ((*real_morecore) (extra_bytes - excess) == 0) + abort (); + + page_break_value += extra_bytes - excess; + } + + /* Zero the space from the end of the "official" break to the actual + break, so that bugs show up faster. */ + bzero (break_value, ((char *) page_break_value - (char *) break_value)); +} + +/* The meat - allocating, freeing, and relocating blocs. */ + +/* These structures are allocated in the malloc arena. + The linked list is kept in order of increasing '.data' members. + The data blocks abut each other; if b->next is non-nil, then + b->data + b->size == b->next->data. */ +typedef struct bp +{ + struct bp *next; + struct bp *prev; + POINTER *variable; + POINTER data; + SIZE size; +} *bloc_ptr; + +#define NIL_BLOC ((bloc_ptr) 0) +#define BLOC_PTR_SIZE (sizeof (struct bp)) + +/* Head and tail of the list of relocatable blocs. */ +static bloc_ptr first_bloc, last_bloc; + +/* Find the bloc referenced by the address in PTR. Returns a pointer + to that block. */ + +static bloc_ptr +find_bloc (ptr) + POINTER *ptr; +{ + register bloc_ptr p = first_bloc; + + while (p != NIL_BLOC) + { + if (p->variable == ptr && p->data == *ptr) + return p; + + p = p->next; + } + + return p; +} + +/* Allocate a bloc of SIZE bytes and append it to the chain of blocs. + Returns a pointer to the new bloc, or zero if we couldn't allocate + memory for the new block. */ + +static bloc_ptr +get_bloc (size) + SIZE size; +{ + register bloc_ptr new_bloc; + + if (! (new_bloc = (bloc_ptr) malloc (BLOC_PTR_SIZE)) + || ! (new_bloc->data = get_more_space (size))) + { + if (new_bloc) + free (new_bloc); + + return 0; + } + + new_bloc->size = size; + new_bloc->next = NIL_BLOC; + new_bloc->variable = (POINTER *) NIL; + + if (first_bloc) + { + new_bloc->prev = last_bloc; + last_bloc->next = new_bloc; + last_bloc = new_bloc; + } + else + { + first_bloc = last_bloc = new_bloc; + new_bloc->prev = NIL_BLOC; + } + + return new_bloc; +} + +/* Relocate all blocs from BLOC on upward in the list to the zone + indicated by ADDRESS. Direction of relocation is determined by + the position of ADDRESS relative to BLOC->data. + + If BLOC is NIL_BLOC, nothing is done. + + Note that ordering of blocs is not affected by this function. */ + +static void +relocate_some_blocs (bloc, address) + bloc_ptr bloc; + POINTER address; +{ + if (bloc != NIL_BLOC) + { + register SIZE offset = address - bloc->data; + register SIZE data_size = 0; + register bloc_ptr b; + + for (b = bloc; b != NIL_BLOC; b = b->next) + { + data_size += b->size; + b->data += offset; + *b->variable = b->data; + } + + safe_bcopy (address - offset, address, data_size); + } +} + + +/* Free BLOC from the chain of blocs, relocating any blocs above it + and returning BLOC->size bytes to the free area. */ + +static void +free_bloc (bloc) + bloc_ptr bloc; +{ + if (bloc == first_bloc && bloc == last_bloc) + { + first_bloc = last_bloc = NIL_BLOC; + } + else if (bloc == last_bloc) + { + last_bloc = bloc->prev; + last_bloc->next = NIL_BLOC; + } + else if (bloc == first_bloc) + { + first_bloc = bloc->next; + first_bloc->prev = NIL_BLOC; + } + else + { + bloc->next->prev = bloc->prev; + bloc->prev->next = bloc->next; + } + + relocate_some_blocs (bloc->next, bloc->data); + relinquish (bloc->size); + free (bloc); +} + +/* Interface routines. */ + +static int use_relocatable_buffers; + +/* Obtain SIZE bytes of storage from the free pool, or the system, as + necessary. If relocatable blocs are in use, this means relocating + them. This function gets plugged into the GNU malloc's __morecore + hook. + + We provide hysteresis, never relocating by less than extra_bytes. + + If we're out of memory, we should return zero, to imitate the other + __morecore hook values - in particular, __default_morecore in the + GNU malloc package. */ + +POINTER +r_alloc_sbrk (size) + long size; +{ + /* This is the first address not currently available for the heap. */ + POINTER top; + /* Amount of empty space below that. */ + /* It is not correct to use SIZE here, because that is usually unsigned. + ptrdiff_t would be okay, but is not always available. + `long' will work in all cases, in practice. */ + long already_available; + POINTER ptr; + + if (! use_relocatable_buffers) + return (*real_morecore) (size); + + top = first_bloc ? first_bloc->data : page_break_value; + already_available = (char *) top - (char *) virtual_break_value; + + /* Do we not have enough gap already? */ + if (size > 0 && already_available < size) + { + /* Get what we need, plus some extra so we can come here less often. */ + SIZE get = size - already_available + extra_bytes; + + if (! obtain (get)) + return 0; + + if (first_bloc) + relocate_some_blocs (first_bloc, first_bloc->data + get); + + /* Zero out the space we just allocated, to help catch bugs + quickly. */ + bzero (virtual_break_value, get); + } + /* Can we keep extra_bytes of gap while freeing at least extra_bytes? */ + else if (size < 0 && already_available - size > 2 * extra_bytes) + { + /* Ok, do so. This is how many to free. */ + SIZE give_back = already_available - size - extra_bytes; + + if (first_bloc) + relocate_some_blocs (first_bloc, first_bloc->data - give_back); + relinquish (give_back); + } + + ptr = virtual_break_value; + virtual_break_value += size; + + return ptr; +} + +/* Allocate a relocatable bloc of storage of size SIZE. A pointer to + the data is returned in *PTR. PTR is thus the address of some variable + which will use the data area. + + If we can't allocate the necessary memory, set *PTR to zero, and + return zero. */ + +POINTER +r_alloc (ptr, size) + POINTER *ptr; + SIZE size; +{ + register bloc_ptr new_bloc; + + if (! r_alloc_initialized) + r_alloc_init (); + + new_bloc = get_bloc (size); + if (new_bloc) + { + new_bloc->variable = ptr; + *ptr = new_bloc->data; + } + else + *ptr = 0; + + return *ptr; +} + +/* Free a bloc of relocatable storage whose data is pointed to by PTR. + Store 0 in *PTR to show there's no block allocated. */ + +void +r_alloc_free (ptr) + register POINTER *ptr; +{ + register bloc_ptr dead_bloc; + + dead_bloc = find_bloc (ptr); + if (dead_bloc == NIL_BLOC) + abort (); + + free_bloc (dead_bloc); + *ptr = 0; +} + +/* Given a pointer at address PTR to relocatable data, resize it to SIZE. + Do this by shifting all blocks above this one up in memory, unless + SIZE is less than or equal to the current bloc size, in which case + do nothing. + + Change *PTR to reflect the new bloc, and return this value. + + If more memory cannot be allocated, then leave *PTR unchanged, and + return zero. */ + +POINTER +r_re_alloc (ptr, size) + POINTER *ptr; + SIZE size; +{ + register bloc_ptr bloc; + + bloc = find_bloc (ptr); + if (bloc == NIL_BLOC) + abort (); + + if (size <= bloc->size) + /* Wouldn't it be useful to actually resize the bloc here? */ + return *ptr; + + if (! obtain (size - bloc->size)) + return 0; + + relocate_some_blocs (bloc->next, bloc->data + size); + + /* Zero out the new space in the bloc, to help catch bugs faster. */ + bzero (bloc->data + bloc->size, size - bloc->size); + + /* Indicate that this block has a new size. */ + bloc->size = size; + + return *ptr; +} + +/* The hook `malloc' uses for the function which gets more space + from the system. */ +extern POINTER (*__morecore) (); + +/* Intialize various things for memory allocation. */ + +static void +r_alloc_init () +{ + if (r_alloc_initialized) + return; + + r_alloc_initialized = 1; + real_morecore = __morecore; + __morecore = r_alloc_sbrk; + + virtual_break_value = break_value = (*real_morecore) (0); + if (break_value == NIL) + abort (); + + page_size = PAGE; + extra_bytes = ROUNDUP (50000); + + page_break_value = (POINTER) ROUNDUP (break_value); + /* Clear the rest of the last page; this memory is in our address space + even though it is after the sbrk value. */ + bzero (break_value, (page_break_value - break_value)); + use_relocatable_buffers = 1; +} diff --git a/gnu/lib/libmalloc/realloc.c b/gnu/lib/libmalloc/realloc.c new file mode 100644 index 00000000000..2d31766a537 --- /dev/null +++ b/gnu/lib/libmalloc/realloc.c @@ -0,0 +1,146 @@ +/* Change the size of a block allocated by `malloc'. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#define min(A, B) ((A) < (B) ? (A) : (B)) + +/* Debugging hook for realloc. */ +__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); + +/* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both free and malloc. */ +__ptr_t +realloc (ptr, size) + __ptr_t ptr; + size_t size; +{ + __ptr_t result; + int type; + size_t block, blocks, oldlimit; + + if (size == 0) + { + free (ptr); + return malloc (0); + } + else if (ptr == NULL) + return malloc (size); + + if (__realloc_hook != NULL) + return (*__realloc_hook) (ptr, size); + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) + { + result = malloc (size); + if (result != NULL) + { + memcpy (result, ptr, size); + free (ptr); + return result; + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY (size); + if (blocks < _heapinfo[block].busy.info.size) + { + /* The new size is smaller; return + excess memory to the free list. */ + _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.info.size + = _heapinfo[block].busy.info.size - blocks; + _heapinfo[block].busy.info.size = blocks; + free (ADDRESS (block + blocks)); + result = ptr; + } + else if (blocks == _heapinfo[block].busy.info.size) + /* No size change necessary. */ + result = ptr; + else + { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = _heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = _heaplimit; + _heaplimit = 0; + free (ptr); + _heaplimit = oldlimit; + result = malloc (size); + if (result == NULL) + { + /* Now we're really in trouble. We have to unfree + the thing we just freed. Unfortunately it might + have been coalesced with its neighbors. */ + if (_heapindex == block) + (void) malloc (blocks * BLOCKSIZE); + else + { + __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE); + (void) malloc (blocks * BLOCKSIZE); + free (previous); + } + return NULL; + } + if (ptr != result) + memmove (result, ptr, blocks * BLOCKSIZE); + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) + /* The new size is the same kind of fragment. */ + result = ptr; + else + { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = malloc (size); + if (result == NULL) + return NULL; + memcpy (result, ptr, min (size, (size_t) 1 << type)); + free (ptr); + } + break; + } + + return result; +} diff --git a/gnu/lib/libmalloc/shlib_version b/gnu/lib/libmalloc/shlib_version new file mode 100644 index 00000000000..97c9f92d6b8 --- /dev/null +++ b/gnu/lib/libmalloc/shlib_version @@ -0,0 +1,2 @@ +major=0 +minor=0 diff --git a/gnu/lib/libmalloc/valloc.c b/gnu/lib/libmalloc/valloc.c new file mode 100644 index 00000000000..fcf117447f0 --- /dev/null +++ b/gnu/lib/libmalloc/valloc.c @@ -0,0 +1,44 @@ +/* Allocate memory on a page boundary. + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include <malloc.h> +#endif + +#ifdef __GNU_LIBRARY__ +extern size_t __getpagesize __P ((void)); +#else +#include "getpagesize.h" +#define __getpagesize() getpagesize() +#endif + +static size_t pagesize; + +__ptr_t +valloc (size) + size_t size; +{ + if (pagesize == 0) + pagesize = __getpagesize (); + + return memalign (pagesize, size); +} diff --git a/gnu/lib/libmalloc/vm-limit.c b/gnu/lib/libmalloc/vm-limit.c new file mode 100644 index 00000000000..a2ac96ce4c8 --- /dev/null +++ b/gnu/lib/libmalloc/vm-limit.c @@ -0,0 +1,134 @@ +/* Functions for memory limit warnings. + Copyright (C) 1990, 1992 Free Software Foundation, Inc. + + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifdef emacs +#include "config.h" +#include "lisp.h" +#endif + +#ifndef emacs +#include <stddef.h> +typedef size_t SIZE; +typedef void *POINTER; +#define EXCEEDS_LISP_PTR(x) 0 +#endif + +#include "mem-limits.h" + +/* + Level number of warnings already issued. + 0 -- no warnings issued. + 1 -- 75% warning already issued. + 2 -- 85% warning already issued. + 3 -- 95% warning issued; keep warning frequently. +*/ +static int warnlevel; + +/* Function to call to issue a warning; + 0 means don't issue them. */ +static void (*warn_function) (); + +/* Get more memory space, complaining if we're near the end. */ + +static void +check_memory_limits () +{ + extern POINTER (*__morecore) (); + + register POINTER cp; + int five_percent; + int data_size; + + if (lim_data == 0) + get_lim_data (); + five_percent = lim_data / 20; + + /* Find current end of memory and issue warning if getting near max */ + cp = (char *) (*__morecore) (0); + data_size = (char *) cp - (char *) data_space_start; + + if (warn_function) + switch (warnlevel) + { + case 0: + if (data_size > five_percent * 15) + { + warnlevel++; + (*warn_function) ("Warning: past 75% of memory limit"); + } + break; + + case 1: + if (data_size > five_percent * 17) + { + warnlevel++; + (*warn_function) ("Warning: past 85% of memory limit"); + } + break; + + case 2: + if (data_size > five_percent * 19) + { + warnlevel++; + (*warn_function) ("Warning: past 95% of memory limit"); + } + break; + + default: + (*warn_function) ("Warning: past acceptable memory limits"); + break; + } + + /* If we go down below 70% full, issue another 75% warning + when we go up again. */ + if (data_size < five_percent * 14) + warnlevel = 0; + /* If we go down below 80% full, issue another 85% warning + when we go up again. */ + else if (warnlevel > 1 && data_size < five_percent * 16) + warnlevel = 1; + /* If we go down below 90% full, issue another 95% warning + when we go up again. */ + else if (warnlevel > 2 && data_size < five_percent * 18) + warnlevel = 2; + + if (EXCEEDS_LISP_PTR (cp)) + (*warn_function) ("Warning: memory in use exceeds lisp pointer size"); +} + +/* Cause reinitialization based on job parameters; + also declare where the end of pure storage is. */ + +void +memory_warnings (start, warnfun) + POINTER start; + void (*warnfun) (); +{ + extern void (* __after_morecore_hook) (); /* From gmalloc.c */ + + if (start) + data_space_start = start; + else + data_space_start = start_of_data (); + + warn_function = warnfun; + __after_morecore_hook = check_memory_limits; +} |