commit 3a43130da66d72f35ab69f09a7a9bf0bfac4054b Author: mccallum Date: Fri Nov 4 16:29:24 1994 +0000 Initial revision git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1 72102866-910b-0410-8b05-ffd578937521 diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..a43ea2126 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 000000000..eb685a5ec --- /dev/null +++ b/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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/CREDITS b/CREDITS new file mode 100644 index 000000000..1fe9ef97e --- /dev/null +++ b/CREDITS @@ -0,0 +1,23 @@ +*** Thanks to **** + +Paul Kunz, Paul Burchard, Kresten Krab Thorup, Matthias Klose, Stefan +Reich, Seth Tisue, Allan Clearwaters, Niels Mvller for bug reports and +suggestions. + +James Gledhill, Allan Clearwaters, Galen Hunt and Jonas Karlsson for +help with testing on different architectures. + +Adam Fedor for contributing the NXStringTable class. Kresten Thorup +for contributing the GapArray class. + +Geoffrey Knauth, the GNU Objective C project coordinator. + +Kresten Krab Thorup for writing the GNU Objective C runtime. + +Richard Stallman for his advice, for emacs, for GNU, and for the FSF. + +Jim Wilson at Cygnus Support for help with IRIX4 nested function +problems. + + -- Andrew + mccallum@gnu.ai.mit.edu diff --git a/Documentation/announce.texi b/Documentation/announce.texi new file mode 100644 index 000000000..96064524d --- /dev/null +++ b/Documentation/announce.texi @@ -0,0 +1,135 @@ +@chapter GNU Objective C Class Library + +@c set the vars OBJECTS_VERSION and OBJECTS_GCC_VERSION +@include version.texi + +The GNU Objective C Class Library, version @value{OBJECTS_VERSION}, is now +available. + +@section What is the GNU Objective C Class Library? + +It is a library of general-purpose, non-graphical Objective C objects +designed in the Smalltalk tradition. It includes collection objects for +maintaining groups of objects and C types, streams for I/O to various +destinations, coders for formating objects and C types to streams, ports +for network packet transmission, distributed objects (remote object +messaging), pseudo-random number generators, and time handling +facilities. + +@ignore +So that developers of non-free, commercial programs can use the library, +the library is released under the GNU Library GPL. + +So that it can easily be included in non-free, comercial software, the +library is released under the GNU Library GPL. + +For more details, see the @samp{README} file that comes with the +distribution. +@end ignore + +@c @section What's new in this release? +@include news.texi + +@section Where can you get it? How can you compile it? + +The libobjects-@value{OBJECTS_VERSION}.tar.gz distribution file has been +placed on @samp{prep.ai.mit.edu} in @samp{/pub/gnu}, and will be +appearing on the usual mirror sites. + +@ignore +The library is available by anonymous ftp at URL: +@smallexample +ftp://prep.ai.mit.edu/pub/gnu/libobjects-@value{OBJECTS_VERSION}.tar.gz +@end smallexample +Since @samp{prep} is heavily loaded, you are encouraged to use GNU +mirror sites. A partial list of mirror sites is at the end of this +message. +@end ignore + +The library requires gcc @value{OBJECTS_GCC_VERSION} or higher. The +library does not work with the NEXTSTEP 3.2 compiler because that +version of NeXT's cc cannot handle nested functions. Until a later +release from NeXT, NEXTSTEP users will have to install gcc. See the +@samp{INSTALL} file for more instructions about compiling and installing +the library. + +The library has been successfully compiled and tested with the following +configurations: +@smallexample + mips-sgi-irix5.2 + sparc-sun-sunos4.1.3 + m68k-next-nextstep3.0 +@end smallexample + +Some previous snapshots of the library worked with these configurations, +but they haven't been tested recently: +@smallexample + i386-unknown-linux + i386-sun-solaris2.4 + i386-unknown-sysv4.0 + sparc-sun-solaris2.3 +@end smallexample + +It is known not to work with: +@smallexample + alpha-dec-osf +@end smallexample + +The @samp{.tar} file is compressed with GNU gzip. Gzip can be obtained by +anonymous ftp at any of the GNU archive sites. + +For info about FTP via email, send email to +@samp{ftpmail@@decwrl.dec.com} with no subject line, and two-line body +with line one @samp{help} and line two @samp{quit}. + +The most recent (not necessarily tested) snapshots of the library will +be placed in @samp{ftp://alpha.gnu.ai.mit.edu/gnu}. + +@display +Happy Hacking! + R. Andrew McCallum + mccallum@@gnu.ai.mit.edu +@end display + +@format + + +[ Most GNU software is packed using the GNU `gzip' compression program. + Source code is available on most sites distributing GNU software. + + For information on how to order GNU software on tape, floppy or cd-rom, or + printed GNU manuals, check the file etc/ORDERS in the GNU Emacs distribution + or in GNUinfo/ORDERS on prep, or e-mail a request to: gnu@@prep.ai.mit.edu + + By ordering your GNU software from the FSF, you help us continue to + develop more free software. Media revenues are our primary source of + support. Donations to FSF are deductible on US tax returns. + + The above software will soon be at these ftp sites as well. + Please try them before prep.ai.mit.edu as prep is very busy! + + thanx -gnu@@prep.ai.mit.edu + + ASIA: ftp.cs.titech.ac.jp, utsun.s.u-tokyo.ac.jp:/ftpsync/prep, + cair.kaist.ac.kr:/pub/gnu, ftp.nectec.or.th:/pub/mirrors/gnu + AUSTRALIA: archie.au:/gnu (archie.oz or archie.oz.au for ACSnet) + AFRICA: ftp.sun.ac.za:/pub/gnu + MIDDLE-EAST: ftp.technion.ac.il:/pub/unsupported/gnu + EUROPE: irisa.irisa.fr:/pub/gnu, ftp.univ-lyon1.fr:pub/gnu, + ftp.mcc.ac.uk, unix.hensa.ac.uk:/pub/uunet/systems/gnu, + src.doc.ic.ac.uk:/gnu, ftp.ieunet.ie:pub/gnu, ftp.eunet.ch, + nic.switch.ch:/mirror/gnu, ftp.informatik.rwth-aachen.de:/pub/gnu, + ftp.informatik.tu-muenchen.de, ftp.win.tue.nl:/pub/gnu, + ftp.funet.fi:/pub/gnu, ftp.denet.dk, ftp.stacken.kth.se, isy.liu.se, + ftp.luth.se:/pub/unix/gnu, ftp.sunet.se:/pub/gnu, archive.eu.net + SOUTH AMERICA: ftp.unicamp.br:/pub/gnu + WESTERN CANADA: ftp.cs.ubc.ca:/mirror2/gnu + USA: wuarchive.wustl.edu:/systems/gnu, labrea.stanford.edu, + ftp.digex.net:/pub/gnu, ftp.kpc.com:/pub/mirror/gnu, f.ms.uky.edu:/pub3/gnu, + jaguar.utah.edu:/gnustuff, ftp.hawaii.edu:/mirrors/gnu, + vixen.cso.uiuc.edu:/gnu, mrcnext.cso.uiuc.edu:/pub/gnu, + ftp.cs.columbia.edu:/archives/gnu/prep, col.hp.com:/mirrors/gnu, + gatekeeper.dec.com:/pub/GNU, ftp.uu.net:/systems/gnu + +] +@end format diff --git a/Documentation/gnustep-base.texi b/Documentation/gnustep-base.texi new file mode 100644 index 000000000..7b9d62ef5 --- /dev/null +++ b/Documentation/gnustep-base.texi @@ -0,0 +1,1286 @@ +\input texinfo @c -*-texinfo-*- + +@c %**start of header +@settitle User's Guide to the GNU Objective-C Class Library +@setfilename libobjects.info +@c %**end of header +@defcodeindex cl +@defcodeindex pr +@ignore +I'm using cindex for concepts, findex for methods, functions and macros, +prindex for protocols, and clindex for classes. +@end ignore + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Libobjects:: The GNU Objective C Class Library. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@c set the vars LIBOBJECTS_VERSION and GCC_VERSION +@include version.texi + +@ifinfo +This file documents the features and implementation of The GNU +Objective-C class library. + +Copyright (C) 1993 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through @TeX{} and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +section entitled ``GNU Library General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that the section entitled ``GNU Library General Public License'' and +this permission notice may be included in translations approved by the +Free Software Foundation instead of in the original English. +@end ifinfo + +@iftex +@finalout +@c @smallbook +@c @cropmarks +@end iftex + +@setchapternewpage odd + +@titlepage +@title User's Guide to the +@title GNU Objective C Class Library +@sp 3 +@c @subtitle last updated Oct 26, 1993 +@subtitle Version @value{OBJECTS_VERSION} +@subtitle (for use with @samp{gcc} version @value{GCC_VERSION}) +@author R. Andrew McCallum (mccallum@@gnu.ai.mit.edu) +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1993 Free Software Foundation, Inc. + + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +section entitled ``GNU Library General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that the section entitled ``GNU Library General Public License'' may be +included in a translation approved by the author instead of in the original +English. + +@strong{Note: The GNU Objective-C library is still in alpha release. You will +be performing a valuable service if you report any bugs you encounter.} + +@end titlepage + +@ignore +saved copy +* Copying:: GNU Library Public License says how you can copy + and share libobjects. +* Contributors:: People who have contributed to libobjects. +* Installation:: How to configure, compile and install libobjects. +* Trouble:: If you have trouble installing libobjects. + +* Overview:: libobjects in brief. +* Organization:: The heirarchy of protocols and classes. +* Conventions:: Stylistic conventions and design philosophy. +* Content Types:: Collections can contain C types as well as objects. + +* Creating:: Creating a collection. +* Freeing:: Freeing a collection or its elements. +* Adding:: Adding elements to a collection. +* Removing:: Removing elements from a collection. +* Replacing:: Replacing elements in a collection. +* Enumerating:: Performing an operation with all elements. +* Duplicating:: Making a copy of a collection. +* Archiving:: Writing (and reading) a collection to (from) a file. +* Querying:: Asking questions about a collection and its contents. +* Sorting:: Sorting the contents of a collection. + +* Classes:: Choosing the class with the features you need. + +* Projects:: To do list and questions for users. + +* Protocol Index:: +* Class Index:: +* Method Function Macro Index:: +* Concept Index:: +@end ignore + +@ifinfo +@node Top, Copying, , (DIR) +@top Libobjects + +This manual documents how to install and use the GNU Objective-C +Class Library (or @samp{libobjects}), version +@value{LIBOBJECTS_VERSION}, for use with @samp{gcc} version +@value{GCC_VERSION}. + +It is nothing but a skeleton now, mostly containing rough notes. +In the future it will be fleshed out and the text will be polished. + +@end ifinfo +@menu +* Copying:: GNU Library Public License says how you can copy + and share libobjects. +* Contributors:: People who have contributed to libobjects. +* Installation:: How to configure, compile and install libobjects. +* Trouble:: If you have trouble installing libobjects. + +* Overview:: libobjects in brief. +* Organization:: The heirarchy of protocols and classes. +* Conventions:: Stylistic conventions and design philosophy. +* Content Types:: Collections can contain C types as well as objects. + +* Creating:: Creating a collection. +* Freeing:: Freeing a collection or its elements. +* Adding:: Adding elements to a collection. +* Removing:: Removing elements from a collection. +* Replacing:: Replacing elements in a collection. +* Enumerating:: Performing an operation with all elements. +* Duplicating:: Making a copy of a collection. +* Archiving:: Writing (and reading) a collection to (from) a file. +* Querying:: Asking questions about a collection and its contents. +* Sorting:: Sorting the contents of a collection. + +* Classes:: Choosing the class with the features you need. + +* Projects:: To do list and questions for users. + +* Protocol Index:: +* Class Index:: +* Method Function Macro Index:: +* Concept Index:: + +@end menu + +@node Copying, Contributors, Top, Top +@unnumbered Copying + +See the file @samp{COPYING.LIB}. + +@node Contributors, Installation, Copying, Top +@unnumbered Contributors to GNU Objective-C Collection library + +@itemize @bullet +@item +Andrew McCallum designed the protocol and +class heirarchies, and wrote the otherwise unattributed classes. + +@item +Kresten Krab Thorup made libobjects possible by +writing the GNU Objective-C runtime. He also contributed the GapArray +and Storage classes. He also wrote patches to texinfo that make +@code{deftypemethod} possible. + +@item Adam Fedor wrote the NXStringTable +class. + +@item +Paul Kunz did a lot to fix the List +class. + +@item +Kresten Krab Thorup , Paul Burchard +, Paul Kunz , +Geoffery Knauth , Steve Naroff , +Richard Stallman and others contributed to +discussions about the library. + +@end itemize + +@node Installation, Trouble, Contributors, Top +@chapter Installing GNU Objective-C Class Library + +@include install.texi + + +@node Trouble, Overview, Installation, Top +@chapter Trouble in Installation + +Try to fix the problem. Send patches to mccallum@@gnu.ai.mit.edu. + +<> + + +@node Overview, Organization, Trouble, Top +@chapter Overview + +The GNU classes included in this version of the library fall into five +categories: collections, magnitudes, streams, coders and remote +messaging support. + +@c There are several GNU protocols also. You can recognize the protocols +@c by their name: they all end with ``ing''. + +@itemize + +@item The collection objects all conform to the @samp{Collecting} +protocol. Reading @samp{./objects/Collecting.h} is a good place to +start. Protocols for collections that store their contents with keys +and with indices can be found in @samp{./objects/KeyedCollecting.h} and +@samp{./objects/IndexedCollecting.h} respectively. Examples of generic +collections are @samp{Set} and @samp{Bag}. The keyed collections are +@samp{Dictionary} and @samp{MappedCollector}. The classes @samp{Array}, +@samp{Queue}, @samp{GapArray}, @samp{LinkedList}, @samp{BinaryTree}, +@samp{RBTree} and @samp{SplayTree} are all indexed collections. + +@item The useful magnitude classes are @samp{Time} and @samp{Random}. +The @samp{Random} class works in conjunction with pseudo-random number +generators that conform to the @samp{RandomGenerating} protocol. The +conforming class @samp{RNGBerkeley} provides identical behavior to the +BSD random() function. The class @samp{RNGAdditiveCongruential} is an +implementation of the additive congruential method. + +@item Stream objects provide a consistent interface for reading and +writing bytes. Read @samp{./objects/Stream.h} to get the general idea. +@samp{StdioStream} objects work with files, file descriptors, FILE +pointers and pipes to executables. @samp{MemoryStream} objects work +with memory buffers. + +@item Coders provide a formatted way of writing to Streams. After a +coder is initialized with a stream, the coder can encode/decode +Objective C objects and C types. See @samp{./objects/Coder.h} for the +abstract superclass interface; see @samp{./objects/Coding.h} for the +protocol adopted by objects that read and write themselves using coders. +The currently available concrete coders are @samp{BinaryCoder}, for +reading and writing a compact stream of illegible bytes, and +@samp{TextCoder}, for reading and writing human-readable text. + +Coders and streams can be mixed and matched so that programmers can +choose the destination and the format separately. + +Neither the stream or coder class heirarchies are very mature yet. I +threw them together because I needed them for remote object messaging. + +@item The remote object messaging support classes are @samp{Connection}, +@samp{Proxy}, @samp{ConnectedCoder}, @samp{Port} and @samp{SocketPort}. + +@end itemize + +@node Organization, Conventions, Overview, Top +@chapter Organization + +The library is built around several protocols: + +@itemize + +@item +The protocol is root of the collection protocol heirarchy. +The protocol defines the most general interface to a +collection of elements. Elements can be added, removed, and replaced. +The contents can be tested, enumerated, and enumerated through various +filters. Elements may be objects, or any C type included in the +"elt" union given in elt.h, but all elements of a collection must be of +the same C type. +(For examples see Set and Bag.) + +@item +The protocol inherits from the protocol. +The protocol defines the interface to a +collection of elements that are accessible by a key, where the key is +some unique element. Pairs of (key element, content element) may be +added, removed and replaced. The keys and contents may be tested, +enumerated, and copied. +(For examples see Dictionary and MappedCollector.) + +@item +The protocol inherits from the + protocol. +The protocol defines the interface to a +collection of elements that are accessible by a key that is an index, +where the indeces in a collection are a contiguous series of unsigned +integers beginning at 0. This is the root of the protocol heirarchy +for all collections that hold their elements in some order. Elements +may be accessed, inserted, replaced and removed by their index. +(For examples see Array and LinkedList.) + +@item +The protocol defines the interface to an object +that may be an element in a LinkedList. LinkedList is a collection +object based on a doubly linked list. +(For an example see LinkedListNode.) + +@item +The protocol defines the interface to an object +that may be an element in a BinaryTree. BinaryTree is a collection +object based on a binary trees. +(For an example see BinaryTreeNode.) + +@end itemize + +Here is the object inheritance heirarchy. All collection abtract +superclasses (classes which are not usable without subclassing) end +with "Collection"; all protocols end with "ing"; all collection +protocols end with "Collecting". + +@smallexample + Collection + Set + Bag + KeyedCollection + Dictionary + MappedCollector + IndexedCollection + Array + Stack + GapArray + CircularArray + Queue + Heap + LinkedList + BinaryTree + RBTree + EltNodeCollector + String + DelegateList + + HashTable + List + Storage +@end smallexample + +<> + + +@node Conventions, Content Types, Organization, Top +@chapter Stylistic Conventions and Design Philosophy + +@section Stylistic Conventions + +@itemize @bullet + +@item +Objective-C source files have file extension @file{.m}. Both +C-compatibility header files and class declaration files have extension +@file{.h}. + +@item +Objective-C class names begin with capital letters. Multi-word class +names capitalize each word, with no underscore separation. + +@item +Include files that define Objective-C classes begin with capital letters +(as do the names of the classes themselves). + +@item +All protocols end with @code{ing}. All collection protocols end with +@code{Collecting}. All collection abtract superclasses (classes which +are not usable without subclassing) end with @code{Collection}. + +@item +Include files that supply function prototypes for other C +functions are all lower case. + +@item +Instance variables begin with an underscore, are all lower case, and +have underscores separating their component words. The leading +underscore distinguishes them from local varibles defined inside +methods. + +@item +All include files define a preprocessor variable __X_h_INCLUDE_GNU, +where X is the name of the file, and conditionally compile only if this +has not been already defined. + +@item +The following macros and variables make the relevant version numbers +available: + +@defmac COLL_VERSION +The version number of the collection library. +Declared in @samp{coll/collstd.h} +@end defmac + +@defmac COLL_GCC_VERSION +The version number of the compiler used to compile the collection +library. +Declared in @samp{coll/collstd.h} +@end defmac + +@deftypevar {char[]} coll_version +A string containing the version number of the collection library. +Declared in @samp{coll/collstd.h} +@end deftypevar + +@deftypevar {char[]} coll_gcc_version +A string containing the version number of the compiler used to compile +the collection library. +Declared in @samp{coll/collstd.h} +@end deftypevar + +@end itemize + +@section The design philosophy. + +Objective-C is not Smalltalk. Differences that matter to the +Collection heirarchy: + +@itemize + +@item +There can be only one set of argument types with each selector. +(For instance in Objective-C we can't have "-(double)data" and +"-(char)data". I can't stand it when some library that I'm forced to +load already defines a selector that I want to use with different +types.) This isn't an issue in Smalltalk because everything is an +object. + +I make the Collection method names a little more descriptive, while +keeping them close to Smalltalk. (For instance I think there is a +good reason for using "-addObject:" instead of "-add:") + +@item +We will want collections of int's, float's, and other non-Objects. +Using Objective C wrappers around these C primitive types (i.e. +Integer and Float objects) is not an efficient enough option for all +cases. + +We could create two parallel heirarchies, one for Objects and one +for elements passed as void*, but since so much of the functionality +overlaps, I have merged them, and it doesn't actually look all that +bad. + +@item +Objective C doesn't have Smalltalk Blocks. + +Passing pointers to functions is a reasonable substitute. This is made +easier with gcc's nested functions and the LAMBDA() macro defined in +coll/collstd.h. + +@item +Smalltalk does automatic garbage collection; Objective C doesn't. + +I think it should be made obvious which methods allocate a new +object. Hence "-shallowCopyAs:[Bag class]" instead of +"as:[Bag class]". + +@item +We have usable Collection classes (Set, Bag, Array, etc) with +functionality matching Smalltalk's objects, but there are good +reasons for not having the abstract superclass structure match +Smalltalk exactly. + +@end itemize + +<> + + +@node Content Types, Creating, Conventions, Top +@chapter Content types +@cindex Content types +@cindex Types of storable data + +Collections can hold either objects or primitive C types. More +specifically, collections can hold any of the types in the +@code{elt} union defined in @code{coll/elt.h}. All contents of a +collection must be of the same type. + +You declare which type the collection will hold at collection +initialization time, and the type can not be changed later. You +specify the type using the Objective-C @code{@@encode()} directive. +You can find out the type held by a collection with the method +@code{contentEncoding} (@pxref{Querying}). + +Many operations are independent of the type the collection holds. For +example the method @code{-(unsigned)count} returns the number of members +in the collection. + +Other operations need to take arguments of different types depending on +whether the contents are objects or some other type. In this case there +will be two methods, distinguished by the words @code{Object} and +@code{Element} in their method name. For example, +@code{-removeObject:anObject} vs +@code{-(elt)removeElement:(elt)anElement}. + +<> + +@node Creating, Freeing, Content Types, Top +@chapter Creating a Collection + +@menu +* Basic Creating:: +* Keyed Creating:: +@end menu + +@node Basic Creating, Keyed Creating, , Creating +@section Basic Creating + +@deftypemethod Collection {} @keyword{-init} +@end deftypemethod + +@deftypemethod Collection {} @keyword{-initEncoding:} (const char *)@var{contentEncoding} +@end deftypemethod + +Create with @code{alloc} and @code{init}. Specify the type of contents +using @code{initEncoding:}. For example: + +@smallexample +id arrayHoldingInts = [[Array alloc] initEncoding:@@encode(int)]; +@end smallexample + +<> + +@node Keyed Creating, , Basic Creating, Creating +@section Keyed Creating + + +@node Freeing, Adding, Creating, Top +@chapter Freeing a Collection or its Elements + +You can free all the objects in a collection and empty it using +@code{freeObjects}. You can emtpy a collection without freeing the +contents using @code{empty}. You can free a collection without freeing +the contents using @code{free}. + +<> + + +@node Adding, Removing, Freeing, Top +@chapter Adding Elements to a Collection + +Talk about adding. + +@menu +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +@end menu + +@node Basic Adding, Keyed Adding, , Adding +@section Basic Adding + +Adding, adding if absent, adding a copy, adding all contents of another +collection, adding contents if absent, adding with varargs. + +@deftypemethod Collection {} @keyword{-addObject:} @var{newObject} +@deftypemethodx Collection {} @keyword{-addElement:} (elt)@var{newElement} +Adds @var{newObject} to the receiving collection. Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addObjectIfAbsent:} @var{newObject} +@deftypemethodx Collection {} @keyword{-addElementIfAbsent:} (elt)@var{newElement} +Adds @var{newObject} to the receiving collection only if @var{newObject} +isn't there already. Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addContentsOf:} (id )@var{newObject} +Adds all the elements in @var{aCollection} to the receiving collection. +Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addContentsOfIfAbsent:} (id )@var{newObject} +<> Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addObjectsCount:} (unsigned)@var{count}, ... +@deftypemethodx Collection {} @keyword{-addElementsCount:} (unsigned)@var{count}, ... +<> Returns self. + +Here is an example +@smallexample +id o1 = [[Foo alloc] init]; +id o2 = [[Bar alloc] init]; +id myArray = [[[Array alloc] init] addObjectsCount: 2, o1, o2]; +@end smallexample +@end deftypemethod + +@node Keyed Adding, Indexed Adding, Basic Adding, Adding +@section Keyed Adding + +If the collection's contents are accessible by a key, members can be +inserted at a specified key. See KeyedCollecting protocol. + +@deftypemethod KeyedCollection {} @keyword{-insertObject:} @var{newContentObject} @keyword{atKey:} (elt)@var{aKey} +@deftypemethodx KeyedCollection {} @keyword{-insertElement:} (elt)@var{newContentElement} @keyword{atKey:} (elt)@var{aKey} +<> returns self. +@end deftypemethod + +@node Indexed Adding, , Keyed Adding, Adding +@section Indexed Adding + +Furthermore, if the collections contents are accessible by an index (an +unsigned integer key), members can be appended, prepended. Inserted +members push other members down to make room. +See IndexedCollecting protocol. + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{atIndex:} (unsigned)@var{index} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{atIndex:} (unsigned)@var{index} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{before:} @var{oldObject} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{before:} @var{oldObject} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{after:} @var{oldObject} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{after:} @var{oldObject} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{insertContentsOf:} (id )@var{aCollection} @keyword{atIndex:} (unsigned)@var{index} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-appendObject:} @var{newObject} +@deftypemethodx IndexedCollecting {} @keyword{-appendElement:} (elt)@var{newElement} +@deftypemethodx IndexedCollection {} @keyword{-prependObject:} @var{newObject} +@deftypemethodx IndexedCollecting {} @keyword{-prependElement:} (elt)@var{newElement} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-appendContentsOf:} (id )@var{aCollection} +@deftypemethodx IndexedCollection {} @keyword{-prependContentsOf:} (id )@var{aCollection} +<> returns self. +@end deftypemethod + +<> + + +@node Removing, Replacing, Adding, Top +@chapter Removing Elements from a Collection + +About removing... + +@menu +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +@end menu + +@node Basic Removing, Keyed Removing, , Removing + +@node Keyed Removing, Indexed Removing, Basic Removing, Removing + +@node Indexed Removing, , Keyed Removing, Removing + + +<> + +@node Replacing, Enumerating, Removing, Top +@chapter Replacing Elements in a Collection + +@menu +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +@end menu + +@node Basic Replacing, Keyed Replacing, , Replacing + +@node Keyed Replacing, Indexed Replacing, Basic Replacing, Replacing + +@node Indexed Replacing, , Keyed Replacing, Replacing + +<> + + +@node Enumerating, Duplicating, Replacing, Top +@chapter Enumerating the Contents of a Collection + +Enumeration methods allow you to perform a specified operation on the +members of a collection. You can operate on all the members, operate on +all the members until a flag is set, operate only on the members that +pass some test, or operate on the results of passing the members through +a modifying function. Each of the enumerators come in pairs: one method +for enumerating in place, and another method that is ``safe'' for +enumerating when the operation changes the contents of the receiving +collection. If the contents of the collection are changed during the +enumeration you must use the ``safe'' methods. + +@menu +* Safe vs Unsafe Enumerating:: Enumerations while changing the contents + +* Basic Enumerating:: Enumerations available for all collections +* Keyed Enumerating:: Enumerations on collections with keys +* Indexed Enumerating:: Enumerations on ordered collections + +* LAMBDA:: Defining functions in place with LAMBDA() +@end menu + +@node Safe vs Unsafe Enumerating, Basic Enumerating, , Enumerating +@section Safe vs Unsafe Enumerating + +The simple enumerators operate on the collection in-place. If the +contents of the collection change during the enumeration, you must use +the ``safe'' version of the enumerator instead. + +It works by making a shallow copy of the receiver, performing the +enumeration using the shallow copy, then freeing the shallow copy. + +All enumerators have both ``safe'' and plain versions. + +<> + +@node Basic Enumerating, Keyed Enumerating, Safe vs Unsafe Enumerating, Enumerating +@section Basic Enumerating + +The most basic enumerator is +@deftypemethod Collection {} @keyword{-withObjectsCall:} (void(*)(id))@var{func} +@deftypemethodx Collection {} @keyword{-safeWithObjectsCall:} (void(*)(id))@var{func} +@deftypemethodx Collection {} @keyword{-withElementsCall:} (void(*)(elt))@var{func} +@deftypemethodx Collection {} @keyword{-safeWithElementsCall:} (void(*)(elt))@var{func} +Calls the function @var{func} with each the members of the collection. +Returns self. +@end deftypemethod + +@deftypemethod {Collection} {(void*)} -newEnumState +@end deftypemethod + +@deftypemethod {Collection} {} -freeEnumState: (void**)@var{enumStatePtr} +@end deftypemethod + +@deftypemethod {Collection} {(BOOL)} -getNextObject: (id *)@var{anObjectPtr} @keyword{withEnumState:} (void**)@var{enumState} +@deftypemethodx {Collection} {(BOOL)} -getNextElement: (elt *)@var{anElementPtr} @keyword{withEnumState:} (void**)@var{enumState} +@refill +@end deftypemethod + +@example +void print_first_difference (id coll1, id coll2) + @{ + void *enumState1, *enumState2; + id object1, object2; + + enumState1 = [coll1 newEnumState]; + enumState2 = [coll2 newEnumState]; + while ([coll1 getNextObject:&object1 withEnumState:&enumState1] + && [coll2 getNextObject:&object2 withEnumState:&enumState2]) + @{ + if ([object1 compare:object2]) + @{ + [object1 printForDebugger]; + [object2 printForDebugger]; + @} + @} + [coll1 freeEnumState:&enumState1]; + [coll2 freeEnumState:&enumState2]; + @} +@end example + +@deftypemethod {Collection} {} -withElementsCall: (void(*)(elt))@var{aFunc} @keyword{whileTrue:} (BOOL*)@var{flag} +@deftypemethodx {Collection} {} -safeWithElementsCall: (void(*)(elt))@var{aFunc} @keyword{whileTrue:} (BOOL*)@var{flag} +@refill +@end deftypemethod + + +@node Keyed Enumerating, Indexed Enumerating, Basic Enumerating, Enumerating +@section Keyed Enumerating + + +@node Indexed Enumerating, LAMBDA, Keyed Enumerating, Enumerating +@section Indexed Enumerating + +@deftypemethod {IndexedCollection} {(BOOL)} -getPrevObject: (id *) @var{anObjectPtr} @keyword{withEnumState:} (void**)@var{enumState} +@deftypemethodx {IndexedCollection} {(BOOL)} -getPrevElement: (elt *) @var{anElementPtr} @keyword{withEnumState:} (void**)@var{enumState} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -withObjectsInReverseCall: (void(*)(id))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -safeWithObjectsInReverseCall: (void(*)(id))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -withElementsInReverseCall: (void(*)(elt))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -safeWithElementsInReverseCall: (void(*)(elt))@var{aFunc} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -withObjectsInReverseCall: (void(*)(id)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -safeWithObjectsInReverseCall: (void(*)(id)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -withElementsInReverseCall: (void(*)(elt)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -safeWithElementsInReverseCall: (void(*)(elt)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -makeObjectsPerformInReverse: (SEL) @var{aSel} +@deftypemethodx {IndexedCollection} {} -safeMakeObjectsPerformInReverse: (SEL) @var{aSel} +@deftypemethodx {IndexedCollection} {} -makeObjectsPerformInReverse: (SEL) @var{aSel} @keyword{with:} @var{argObject} +@deftypemethodx {IndexedCollection} {} -safeMakeObjectsPerformInReverse: (SEL) @var{aSel} @keyword{with:} @var{argObject} +@refill +@end deftypemethod + + +@node LAMBDA, , Indexed Enumerating, Enumerating +@section Defining Functions In Place with LAMBDA() +@cindex Defining Functions In Place +@cindex Function definitions with LAMBDA + +NOTE: The LAMBDA macro does not work on all systems. We are waiting +for a general fix. You should avoid using it until then. + +There may not already be a function that does the operation you want +performed during an enumeration. In this case you will have to +write such a function yourself. + +If the function will be used more than once, you should write it as C +functions are usually defined. However, if the function will only be +used for this one enumeration and the function is small, using the +@code{LAMBDA} macro may be easier and more clear. + +@defmac LAMBDA(@var{RETTYPE}, @var{ARGS}, @var{BODY}) +@code{LAMBDA} is a macro for defining a nested function and returning +a pointer to that function. You can use @code{LAMBDA} wherever a +function pointer is required. @var{RETTYPE} is the C type returned by +the function. @var{ARGS} is the parenthesis-enclosed list of arguments +to the function. (Declare them just like in an ANSI function +definition.) @var{BODY} is the curly-bracket-enclosed body of the +function. + +For example, you could create a pointer to a function that adds its +arguments like this: +@smallexample +LAMBDA(int, (int a, int b), @{return a + b;@}) +@end smallexample +@end defmac + +@code{LAMBDA} is particularly convenient for enumeration methods because +the macro can be placed in the position of the method argument. For +instance, you can write: +@example + - fooMethod + @{ + id newColl; + ... + newColl = [self emptyCopyAs:[Array class]]; + [self withObjectsCall: + LAMBDA(void, (id o), @{[newColl addObject:[o copy]];@})]; + return self; + @} +@end example +instead of writing: +@smallexample + - fooMethod + @{ + id newColl = [self emptyCopyAs:[Array class]]; + void myTmpFunc(id o) + @{ + [newColl addObject:[o copy]]; + @} + ... + [self withObjectsCall:myTmpFunc]; + return self; + @} +@end smallexample +In these examples, there may be many lines of code between the +declarations at the top of the method and the @code{withObjectsCall:} at +the bottom of the method. Using @code{LAMBDA} allows you to declare +the function where it is used, instead of arbitrarily far from where it +is used. + +The name @code{LAMBDA} comes from lambda calculus and LISP. + +The @code{LAMBDA} macro and some similar macros are defined in +@samp{coll/collstd.h}. + +@section Filtered Enumerating + +@section Enumerating with Keyed Collections + +@section Enumerating with Indexed Collections + +<> + + +@node Duplicating, Archiving, Enumerating, Top +@chapter Duplicating + +Talk about shallow and deep copies. + +<> + + +@node Archiving, Querying, Duplicating, Top +@chapter Archiving + +You can write collections to a stream. You can read them back in again. +Talk about the @code{-awake} method. + +@deftypemethod Collection {} @keyword{-write:} (TypedStream*)@var{aStream} +<> Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-read:} (TypedStream*)@var{aStream} +<> Returns self. +@end deftypemethod + +<> + + +@node Querying, Sorting, Archiving, Top +@chapter Querying + +<> + +@menu +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Basic Querying, Keyed Querying, , Querying +@section Basic Querying + +@deftypemethod Collection {(BOOL)} @keyword{-isEmpty} +Returns YES if the receiver contains no members; returns NO otherwise. +@end deftypemethod + +@deftypemethod Collection {(const char *)} @keyword{-contentEncoding} +Returns a description of the C type that the receiving collection can +hold. The description is a string of the form returned by the +Objective-C @code{@@encode} directive. +@end deftypemethod + +@node Keyed Querying, Indexed Querying, Basic Querying, Querying +@section Keyed Querying + +@node Indexed Querying, , Keyed Querying, Querying +@section Indexed Querying + +@node Sorting, Classes, Querying, Top +@chapter Sorting + +<> + + +@node Classes, Projects, Sorting, Top +@chapter Choosing the Right Class + +Talk about keys or no keys, ordered or not ordered. Talk about the +classes the require protocol-conforming objects as members. + +@menu +* Set:: +* Bag:: + +* Dictionary:: +* MappedCollector:: + +* Array:: +* Stack:: +* Queue:: +* GapArray:: + +* LinkedList:: +* BinaryTree:: +* RBTree:: +* SplayTree:: +* EltNodeCollector:: + +* Collection:: +* KeyedCollection:: +* IndexedCollection:: +@end menu + +<> + +@node Set, Bag, , Classes +@section Set + +<> + +@node Bag, Dictionary, Set, Classes +@section Bag + +A Bag is ... + +@menu +* Basic Creating:: +* Freeing:: +* Bag Adding:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Bag Removing:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: + + +@end menu + +@node Bag Adding, Bag Removing, , Bag + +@deftypemethod Bag {} @keyword{-addObject:} @var{newObject} withOccurrences: (unsigned)@var{count} +@deftypemethodx Bag {} @keyword{-addElement:} (elt)@var{newElement} withOccurrences: (unsigned)@var{count} +@end deftypemethod + +@node Bag Removing, , Bag Adding, Bag + +@deftypemethod Bag {} @keyword{-removeObject:} @var{oldObject} occurrences: (unsigned)@var{count} +@deftypemethodx Bag {} @keyword{-removeElement:} (elt)@var{oldElement} occurrences: (unsigned)@var{count} +@end deftypemethod + +<> + +@node Dictionary, MappedCollector, Bag, Classes +@section Dictionary + +A Dictionary is ... + +@node MappedCollector, Array, Dictionary, Classes +@section MappedCollector + +A MappedCollector is ... + +@node Array, Stack, MappedCollector, Classes +@section Array + +An Array is ... + +@menu +* Array Capacity Management:: +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Array Capacity Management, , , Array +@section Array Methods + +@deftypemethod {Array} {(unsigned)} @keyword{+defaultCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {(unsigned)} @keyword{+defaultGrowFactor} +@refill +@end deftypemethod + +@deftypemethod {Array} {} @keyword{-initEncoding:} (const char *) +@var{contentEncoding} @keyword{capacity:} (unsigned) @var{aCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {} -setCapacity: (unsigned) @var{newCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {} -setGrowFactor: (unsigned) @var{aNum} +@refill +@end deftypemethod + +@node Stack, Queue, Array, Classes +@section Stack + +@menu +* Stack Methods:: +* Array Capacity Management:: +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Stack Methods, , , Stack + +@deftypemethod {Stack} {} -pushObject: @var{newObject} +@deftypemethodx {Stack} {} -pushElement: (elt)@var{newElement} +@end deftypemethod + +@deftypemethod {Stack} {} -popObject: @var{newObject} +@deftypemethodx {Stack} {} -popElement: (elt)@var{newElement} +@end deftypemethod + +@deftypemethod {Stack} {} -topObject +@deftypemethodx {Stack} {(elt)} -topElement +@end deftypemethod + +@deftypemethod {Stack} {} -exchangeTop +@end deftypemethod + +@node Queue, GapArray, Stack, Classes + +@node GapArray, LinkedList, Queue, Classes + +@node LinkedList, BinaryTree, GapArray, Classes + +@node BinaryTree, RBTree, LinkedList, Classes + +@node RBTree, SplayTree, BinaryTree, Classes + +@node SplayTree, EltNodeCollector, RBTree, Classes + +@node EltNodeCollector, Collection, SplayTree, Classes + +@node Collection, KeyedCollection, EltNodeCollector, Classes + +A Collection is ... + +@menu +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Basic Removing:: +* Basic Replacing:: +* Basic Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +@end menu + +@node KeyedCollection, IndexedCollection, Collection, Classes +@section KeyedCollection + +@menu +* Basic Creating:: +* Keyed Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +@end menu + +@node IndexedCollection, , KeyedCollection, Classes +@section IndexedCollection + +@menu +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + + +@node Projects, Protocol Index, Classes, Top +@chapter To Do List and Questions + +@include todo.texi + +@section How to contribute + +Programmers who have written Objective-C classes that they believe to be +of general interest are encouraged to write to +mccallum@@gnu.ai.mit.edu. Contributing code is not difficult. Here are +some general guidelines: + +@itemize @bullet + +@item +FSF must maintain the right to accept or reject potential contributions. +Generally, the only reasons for rejecting contributions are cases where +they duplicate existing or nearly-released code, contain unremovable +specific machine dependencies, or are somehow incompatible with the +rest of the library. + +@item +Acceptance of contributions means that the code is accepted for adaptation +into libobjects. FSF must reserve the right to make various editorial changes +in code. Very often, this merely entails formatting, maintenance of various +conventions, etc. Contributors are always given authorship credit and shown +the final version for approval. + +@item +Contributors must assign their copyright to FSF via a form sent out +upon acceptance. Assigning copyright to FSF ensures that the code +may be freely distributed. + +@item +Assistance in providing documentation, test files, and debugging +support is strongly encouraged. + +@end itemize + +Extensions, comments, and suggested modifications of existing libobjects +features are also very welcome. + +@node Protocol Index, Class Index, Projects, Top +@unnumbered Protocol Index +@printindex pr + + +@node Class Index, Method Function Macro Index, Protocol Index, Top +@unnumbered Class Index +@printindex cl + + +@node Method Function Macro Index, Concept Index, Class Index, Top +@unnumbered Method, Function and Macro Index +@printindex fn + +@node Concept Index, , Method Function Macro Index, Top +@unnumbered Concept Index +@printindex cp + +@summarycontents +@contents + +@bye diff --git a/Documentation/install.texi b/Documentation/install.texi new file mode 100644 index 000000000..b20ea6a48 --- /dev/null +++ b/Documentation/install.texi @@ -0,0 +1,175 @@ +@c This is a generic INSTALL file for utilities distributions. +@c If this package does not come with, e.g., installable documentation or +@c data files, please ignore the references to them below. + +@c set the vars OBJECTS_VERSION and OBJECTS_GCC_VERSION +@include version.texi + +@ifset INSTALL_ONLY +This file documents the installation of the GNU Objective C +Class Library, @samp{libobjects}. Copyright (C) 1993, 1994 Free Software +Foundation, Inc. You may copy, distribute, and modify it freely as long +as you preserve this copyright notice and permission notice. +@chapter Installing @samp{libobjects} +@end ifset + +To compile and install @samp{libobjects}: + +@enumerate + +@item +Install @samp{gcc}. The library requires gcc version +@value{OBJECTS_GCC_VERSION} or later. + +@item +Configure the package for your system. In the directory that this file +is in, type @samp{./configure}. If you're using @samp{csh} on an old +version of System V, you might need to type @samp{sh configure} instead +to prevent @samp{csh} from trying to execute @samp{configure} itself. + +If you are compiling the library for a NeXT machine, you have the choice +of using either the GNU or the NeXT Objective C runtime. You can +specify this by setting CFLAGS. For example: +@smallexample +CFLAGS=-fgnu-runtime ./configure +@end smallexample + +The @samp{configure} shell script attempts to guess correct values for +various system-dependent variables used during compilation, and creates +the Makefile(s) (one in each subdirectory of the source directory). In +some packages it creates a C header file containing system-dependent +definitions. It also creates a file @samp{config.status} that you can +run in the future to recreate the current configuration. + +Running @samp{configure} takes less than a minute or two. While it is +running, it prints some messages that tell what it is doing. If you +don't want to see the messages, run @samp{configure} with its standard +output redirected to @samp{/dev/null}; for example: +@smallexample +./configure >/dev/null +@end smallexample + +To compile the package in a different directory from the one containing +the source code, you must use a version of make that supports the VPATH +variable, such as GNU make. @samp{cd} to the directory where you want +the object files and executables to go and run @samp{configure}. +@samp{configure} automatically checks for the source code in the +directory that @samp{configure} is in and in @samp{..}. If for some +reason @samp{configure} is not in the source code directory that you are +configuring, then it will report that it can't find the source code. In +that case, run @samp{configure} with the option @samp{--srcdir=DIR}, +where DIR is the directory that contains the source code. + +By default, @samp{make install} will install the package's files in +/usr/local/bin, /usr/local/lib, /usr/local/man, etc. You can specify +an installation prefix other than /usr/local by giving @samp{configure} the +option @samp{--prefix=PATH}. Alternately, you can do so by giving a value +for the @samp{prefix} variable when you run @samp{make}, e.g., +@smallexample +make prefix=/usr/gnu +@end smallexample + +You can specify separate installation prefixes for architecture-specific +files and architecture-independent files. If you give @samp{configure} +the option @samp{--exec_prefix=PATH} or set the @samp{make} variable +@samp{exec_prefix} to PATH, the package will use PATH as the prefix for +installing programs and libraries. Data files and documentation will +still use the regular prefix. Normally, all files are installed using +the regular prefix. + +You can tell @samp{configure} to figure out the configuration for your +system, and record it in @samp{config.status}, without actually +configuring the package (creating @samp{Makefile}s and perhaps a +configuration header file). To do this, give @samp{configure} the +@samp{--no-create} option. Later, you can run @samp{./config.status} to +actually configure the package. This option is useful mainly in +@samp{Makefile} rules for updating @samp{config.status} and +@samp{Makefile}. You can also give @samp{config.status} the +@samp{--recheck} option, which makes it re-run @samp{configure} with the +same arguments you used before. This is useful if you change +@samp{configure}. + +@samp{configure} ignores any other arguments that you give it. + +If your system requires unusual options for compilation or linking that +@samp{configure} doesn't know about, you can give @samp{configure} +initial values for some variables by setting them in the environment. +In Bourne-compatible shells, you can do that on the command line like +this: +@smallexample +CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure +@end smallexample + +The @samp{make} variables that you might want to override with environment +variables when running @samp{configure} are: + +(For these variables, any value given in the environment overrides the +value that @samp{configure} would choose:) +@table @samp + +@item CC +C compiler program. Default is @samp{cc}, or @samp{gcc} if @samp{gcc} +is in your PATH. + +@item INSTALL +Program to use to install files. +Default is @samp{install} if you have it, @samp{install.sh} otherwise. +@end table + + +(For these variables, any value given in the environment is added to +the value that @samp{configure} chooses:) +@table @samp + +@item DEFS +Configuration options, in the form @samp{-Dfoo -Dbar ...} + +@item LIBS +Libraries to link with, in the form @samp{-lfoo -lbar ...} +@end table + +If you need to do unusual things to compile the package, we encourage +you to figure out how @samp{configure} could check whether to do them, and +mail diffs or instructions to the address given in the @samp{README} so we +can include them in the next release. + + +@item +Type @samp{make} to compile the package. If you want, you can override +the @samp{make} variables @samp{CFLAGS} and @samp{LDFLAGS} like this: +@smallexample + make CFLAGS=-O2 LDFLAGS=-s +@end smallexample + +You will get some warnings from @samp{#warning} lines I've added to the +code. Ignore them. + +You may get some warnings like @samp{stdobjects.m:0: warning: +`_OBJC_SELECTOR_TABLE' defined but not used}. Ignore them. +They are bogus warnings due to a bug in cc1obj. + +You may get some warnings like @samp{ar: filename BinaryTreeEltNode.o +truncated to BinaryTreeEltNo}. Ignore them. + + +@item +If you want to compile the self-tests, cd to @samp{checks} and type +@samp{make}. If you want to compile the examples, cd to @samp{examples} +and type @samp{make}. + +@item +Type @samp{make install} to install programs, data files, and +documentation. + +@item +You can remove the program binaries and object files from the source +directory by typing @samp{make clean}. To also remove the Makefile(s), +and @samp{config.status} (all the files that @samp{configure} created), +type @samp{make distclean}. + +The file @samp{configure.in} is used as a template to create +@samp{configure} by a program called @samp{autoconf}. You will only +need it if you want to regenerate @samp{configure} using a newer version +of @samp{autoconf}. + +@end enumerate diff --git a/Documentation/libobjects.texi b/Documentation/libobjects.texi new file mode 100644 index 000000000..7b9d62ef5 --- /dev/null +++ b/Documentation/libobjects.texi @@ -0,0 +1,1286 @@ +\input texinfo @c -*-texinfo-*- + +@c %**start of header +@settitle User's Guide to the GNU Objective-C Class Library +@setfilename libobjects.info +@c %**end of header +@defcodeindex cl +@defcodeindex pr +@ignore +I'm using cindex for concepts, findex for methods, functions and macros, +prindex for protocols, and clindex for classes. +@end ignore + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Libobjects:: The GNU Objective C Class Library. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@c set the vars LIBOBJECTS_VERSION and GCC_VERSION +@include version.texi + +@ifinfo +This file documents the features and implementation of The GNU +Objective-C class library. + +Copyright (C) 1993 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through @TeX{} and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +section entitled ``GNU Library General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that the section entitled ``GNU Library General Public License'' and +this permission notice may be included in translations approved by the +Free Software Foundation instead of in the original English. +@end ifinfo + +@iftex +@finalout +@c @smallbook +@c @cropmarks +@end iftex + +@setchapternewpage odd + +@titlepage +@title User's Guide to the +@title GNU Objective C Class Library +@sp 3 +@c @subtitle last updated Oct 26, 1993 +@subtitle Version @value{OBJECTS_VERSION} +@subtitle (for use with @samp{gcc} version @value{GCC_VERSION}) +@author R. Andrew McCallum (mccallum@@gnu.ai.mit.edu) +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1993 Free Software Foundation, Inc. + + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +section entitled ``GNU Library General Public License'' is included exactly as +in the original, and provided that the entire resulting derived work is +distributed under the terms of a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that the section entitled ``GNU Library General Public License'' may be +included in a translation approved by the author instead of in the original +English. + +@strong{Note: The GNU Objective-C library is still in alpha release. You will +be performing a valuable service if you report any bugs you encounter.} + +@end titlepage + +@ignore +saved copy +* Copying:: GNU Library Public License says how you can copy + and share libobjects. +* Contributors:: People who have contributed to libobjects. +* Installation:: How to configure, compile and install libobjects. +* Trouble:: If you have trouble installing libobjects. + +* Overview:: libobjects in brief. +* Organization:: The heirarchy of protocols and classes. +* Conventions:: Stylistic conventions and design philosophy. +* Content Types:: Collections can contain C types as well as objects. + +* Creating:: Creating a collection. +* Freeing:: Freeing a collection or its elements. +* Adding:: Adding elements to a collection. +* Removing:: Removing elements from a collection. +* Replacing:: Replacing elements in a collection. +* Enumerating:: Performing an operation with all elements. +* Duplicating:: Making a copy of a collection. +* Archiving:: Writing (and reading) a collection to (from) a file. +* Querying:: Asking questions about a collection and its contents. +* Sorting:: Sorting the contents of a collection. + +* Classes:: Choosing the class with the features you need. + +* Projects:: To do list and questions for users. + +* Protocol Index:: +* Class Index:: +* Method Function Macro Index:: +* Concept Index:: +@end ignore + +@ifinfo +@node Top, Copying, , (DIR) +@top Libobjects + +This manual documents how to install and use the GNU Objective-C +Class Library (or @samp{libobjects}), version +@value{LIBOBJECTS_VERSION}, for use with @samp{gcc} version +@value{GCC_VERSION}. + +It is nothing but a skeleton now, mostly containing rough notes. +In the future it will be fleshed out and the text will be polished. + +@end ifinfo +@menu +* Copying:: GNU Library Public License says how you can copy + and share libobjects. +* Contributors:: People who have contributed to libobjects. +* Installation:: How to configure, compile and install libobjects. +* Trouble:: If you have trouble installing libobjects. + +* Overview:: libobjects in brief. +* Organization:: The heirarchy of protocols and classes. +* Conventions:: Stylistic conventions and design philosophy. +* Content Types:: Collections can contain C types as well as objects. + +* Creating:: Creating a collection. +* Freeing:: Freeing a collection or its elements. +* Adding:: Adding elements to a collection. +* Removing:: Removing elements from a collection. +* Replacing:: Replacing elements in a collection. +* Enumerating:: Performing an operation with all elements. +* Duplicating:: Making a copy of a collection. +* Archiving:: Writing (and reading) a collection to (from) a file. +* Querying:: Asking questions about a collection and its contents. +* Sorting:: Sorting the contents of a collection. + +* Classes:: Choosing the class with the features you need. + +* Projects:: To do list and questions for users. + +* Protocol Index:: +* Class Index:: +* Method Function Macro Index:: +* Concept Index:: + +@end menu + +@node Copying, Contributors, Top, Top +@unnumbered Copying + +See the file @samp{COPYING.LIB}. + +@node Contributors, Installation, Copying, Top +@unnumbered Contributors to GNU Objective-C Collection library + +@itemize @bullet +@item +Andrew McCallum designed the protocol and +class heirarchies, and wrote the otherwise unattributed classes. + +@item +Kresten Krab Thorup made libobjects possible by +writing the GNU Objective-C runtime. He also contributed the GapArray +and Storage classes. He also wrote patches to texinfo that make +@code{deftypemethod} possible. + +@item Adam Fedor wrote the NXStringTable +class. + +@item +Paul Kunz did a lot to fix the List +class. + +@item +Kresten Krab Thorup , Paul Burchard +, Paul Kunz , +Geoffery Knauth , Steve Naroff , +Richard Stallman and others contributed to +discussions about the library. + +@end itemize + +@node Installation, Trouble, Contributors, Top +@chapter Installing GNU Objective-C Class Library + +@include install.texi + + +@node Trouble, Overview, Installation, Top +@chapter Trouble in Installation + +Try to fix the problem. Send patches to mccallum@@gnu.ai.mit.edu. + +<> + + +@node Overview, Organization, Trouble, Top +@chapter Overview + +The GNU classes included in this version of the library fall into five +categories: collections, magnitudes, streams, coders and remote +messaging support. + +@c There are several GNU protocols also. You can recognize the protocols +@c by their name: they all end with ``ing''. + +@itemize + +@item The collection objects all conform to the @samp{Collecting} +protocol. Reading @samp{./objects/Collecting.h} is a good place to +start. Protocols for collections that store their contents with keys +and with indices can be found in @samp{./objects/KeyedCollecting.h} and +@samp{./objects/IndexedCollecting.h} respectively. Examples of generic +collections are @samp{Set} and @samp{Bag}. The keyed collections are +@samp{Dictionary} and @samp{MappedCollector}. The classes @samp{Array}, +@samp{Queue}, @samp{GapArray}, @samp{LinkedList}, @samp{BinaryTree}, +@samp{RBTree} and @samp{SplayTree} are all indexed collections. + +@item The useful magnitude classes are @samp{Time} and @samp{Random}. +The @samp{Random} class works in conjunction with pseudo-random number +generators that conform to the @samp{RandomGenerating} protocol. The +conforming class @samp{RNGBerkeley} provides identical behavior to the +BSD random() function. The class @samp{RNGAdditiveCongruential} is an +implementation of the additive congruential method. + +@item Stream objects provide a consistent interface for reading and +writing bytes. Read @samp{./objects/Stream.h} to get the general idea. +@samp{StdioStream} objects work with files, file descriptors, FILE +pointers and pipes to executables. @samp{MemoryStream} objects work +with memory buffers. + +@item Coders provide a formatted way of writing to Streams. After a +coder is initialized with a stream, the coder can encode/decode +Objective C objects and C types. See @samp{./objects/Coder.h} for the +abstract superclass interface; see @samp{./objects/Coding.h} for the +protocol adopted by objects that read and write themselves using coders. +The currently available concrete coders are @samp{BinaryCoder}, for +reading and writing a compact stream of illegible bytes, and +@samp{TextCoder}, for reading and writing human-readable text. + +Coders and streams can be mixed and matched so that programmers can +choose the destination and the format separately. + +Neither the stream or coder class heirarchies are very mature yet. I +threw them together because I needed them for remote object messaging. + +@item The remote object messaging support classes are @samp{Connection}, +@samp{Proxy}, @samp{ConnectedCoder}, @samp{Port} and @samp{SocketPort}. + +@end itemize + +@node Organization, Conventions, Overview, Top +@chapter Organization + +The library is built around several protocols: + +@itemize + +@item +The protocol is root of the collection protocol heirarchy. +The protocol defines the most general interface to a +collection of elements. Elements can be added, removed, and replaced. +The contents can be tested, enumerated, and enumerated through various +filters. Elements may be objects, or any C type included in the +"elt" union given in elt.h, but all elements of a collection must be of +the same C type. +(For examples see Set and Bag.) + +@item +The protocol inherits from the protocol. +The protocol defines the interface to a +collection of elements that are accessible by a key, where the key is +some unique element. Pairs of (key element, content element) may be +added, removed and replaced. The keys and contents may be tested, +enumerated, and copied. +(For examples see Dictionary and MappedCollector.) + +@item +The protocol inherits from the + protocol. +The protocol defines the interface to a +collection of elements that are accessible by a key that is an index, +where the indeces in a collection are a contiguous series of unsigned +integers beginning at 0. This is the root of the protocol heirarchy +for all collections that hold their elements in some order. Elements +may be accessed, inserted, replaced and removed by their index. +(For examples see Array and LinkedList.) + +@item +The protocol defines the interface to an object +that may be an element in a LinkedList. LinkedList is a collection +object based on a doubly linked list. +(For an example see LinkedListNode.) + +@item +The protocol defines the interface to an object +that may be an element in a BinaryTree. BinaryTree is a collection +object based on a binary trees. +(For an example see BinaryTreeNode.) + +@end itemize + +Here is the object inheritance heirarchy. All collection abtract +superclasses (classes which are not usable without subclassing) end +with "Collection"; all protocols end with "ing"; all collection +protocols end with "Collecting". + +@smallexample + Collection + Set + Bag + KeyedCollection + Dictionary + MappedCollector + IndexedCollection + Array + Stack + GapArray + CircularArray + Queue + Heap + LinkedList + BinaryTree + RBTree + EltNodeCollector + String + DelegateList + + HashTable + List + Storage +@end smallexample + +<> + + +@node Conventions, Content Types, Organization, Top +@chapter Stylistic Conventions and Design Philosophy + +@section Stylistic Conventions + +@itemize @bullet + +@item +Objective-C source files have file extension @file{.m}. Both +C-compatibility header files and class declaration files have extension +@file{.h}. + +@item +Objective-C class names begin with capital letters. Multi-word class +names capitalize each word, with no underscore separation. + +@item +Include files that define Objective-C classes begin with capital letters +(as do the names of the classes themselves). + +@item +All protocols end with @code{ing}. All collection protocols end with +@code{Collecting}. All collection abtract superclasses (classes which +are not usable without subclassing) end with @code{Collection}. + +@item +Include files that supply function prototypes for other C +functions are all lower case. + +@item +Instance variables begin with an underscore, are all lower case, and +have underscores separating their component words. The leading +underscore distinguishes them from local varibles defined inside +methods. + +@item +All include files define a preprocessor variable __X_h_INCLUDE_GNU, +where X is the name of the file, and conditionally compile only if this +has not been already defined. + +@item +The following macros and variables make the relevant version numbers +available: + +@defmac COLL_VERSION +The version number of the collection library. +Declared in @samp{coll/collstd.h} +@end defmac + +@defmac COLL_GCC_VERSION +The version number of the compiler used to compile the collection +library. +Declared in @samp{coll/collstd.h} +@end defmac + +@deftypevar {char[]} coll_version +A string containing the version number of the collection library. +Declared in @samp{coll/collstd.h} +@end deftypevar + +@deftypevar {char[]} coll_gcc_version +A string containing the version number of the compiler used to compile +the collection library. +Declared in @samp{coll/collstd.h} +@end deftypevar + +@end itemize + +@section The design philosophy. + +Objective-C is not Smalltalk. Differences that matter to the +Collection heirarchy: + +@itemize + +@item +There can be only one set of argument types with each selector. +(For instance in Objective-C we can't have "-(double)data" and +"-(char)data". I can't stand it when some library that I'm forced to +load already defines a selector that I want to use with different +types.) This isn't an issue in Smalltalk because everything is an +object. + +I make the Collection method names a little more descriptive, while +keeping them close to Smalltalk. (For instance I think there is a +good reason for using "-addObject:" instead of "-add:") + +@item +We will want collections of int's, float's, and other non-Objects. +Using Objective C wrappers around these C primitive types (i.e. +Integer and Float objects) is not an efficient enough option for all +cases. + +We could create two parallel heirarchies, one for Objects and one +for elements passed as void*, but since so much of the functionality +overlaps, I have merged them, and it doesn't actually look all that +bad. + +@item +Objective C doesn't have Smalltalk Blocks. + +Passing pointers to functions is a reasonable substitute. This is made +easier with gcc's nested functions and the LAMBDA() macro defined in +coll/collstd.h. + +@item +Smalltalk does automatic garbage collection; Objective C doesn't. + +I think it should be made obvious which methods allocate a new +object. Hence "-shallowCopyAs:[Bag class]" instead of +"as:[Bag class]". + +@item +We have usable Collection classes (Set, Bag, Array, etc) with +functionality matching Smalltalk's objects, but there are good +reasons for not having the abstract superclass structure match +Smalltalk exactly. + +@end itemize + +<> + + +@node Content Types, Creating, Conventions, Top +@chapter Content types +@cindex Content types +@cindex Types of storable data + +Collections can hold either objects or primitive C types. More +specifically, collections can hold any of the types in the +@code{elt} union defined in @code{coll/elt.h}. All contents of a +collection must be of the same type. + +You declare which type the collection will hold at collection +initialization time, and the type can not be changed later. You +specify the type using the Objective-C @code{@@encode()} directive. +You can find out the type held by a collection with the method +@code{contentEncoding} (@pxref{Querying}). + +Many operations are independent of the type the collection holds. For +example the method @code{-(unsigned)count} returns the number of members +in the collection. + +Other operations need to take arguments of different types depending on +whether the contents are objects or some other type. In this case there +will be two methods, distinguished by the words @code{Object} and +@code{Element} in their method name. For example, +@code{-removeObject:anObject} vs +@code{-(elt)removeElement:(elt)anElement}. + +<> + +@node Creating, Freeing, Content Types, Top +@chapter Creating a Collection + +@menu +* Basic Creating:: +* Keyed Creating:: +@end menu + +@node Basic Creating, Keyed Creating, , Creating +@section Basic Creating + +@deftypemethod Collection {} @keyword{-init} +@end deftypemethod + +@deftypemethod Collection {} @keyword{-initEncoding:} (const char *)@var{contentEncoding} +@end deftypemethod + +Create with @code{alloc} and @code{init}. Specify the type of contents +using @code{initEncoding:}. For example: + +@smallexample +id arrayHoldingInts = [[Array alloc] initEncoding:@@encode(int)]; +@end smallexample + +<> + +@node Keyed Creating, , Basic Creating, Creating +@section Keyed Creating + + +@node Freeing, Adding, Creating, Top +@chapter Freeing a Collection or its Elements + +You can free all the objects in a collection and empty it using +@code{freeObjects}. You can emtpy a collection without freeing the +contents using @code{empty}. You can free a collection without freeing +the contents using @code{free}. + +<> + + +@node Adding, Removing, Freeing, Top +@chapter Adding Elements to a Collection + +Talk about adding. + +@menu +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +@end menu + +@node Basic Adding, Keyed Adding, , Adding +@section Basic Adding + +Adding, adding if absent, adding a copy, adding all contents of another +collection, adding contents if absent, adding with varargs. + +@deftypemethod Collection {} @keyword{-addObject:} @var{newObject} +@deftypemethodx Collection {} @keyword{-addElement:} (elt)@var{newElement} +Adds @var{newObject} to the receiving collection. Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addObjectIfAbsent:} @var{newObject} +@deftypemethodx Collection {} @keyword{-addElementIfAbsent:} (elt)@var{newElement} +Adds @var{newObject} to the receiving collection only if @var{newObject} +isn't there already. Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addContentsOf:} (id )@var{newObject} +Adds all the elements in @var{aCollection} to the receiving collection. +Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addContentsOfIfAbsent:} (id )@var{newObject} +<> Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-addObjectsCount:} (unsigned)@var{count}, ... +@deftypemethodx Collection {} @keyword{-addElementsCount:} (unsigned)@var{count}, ... +<> Returns self. + +Here is an example +@smallexample +id o1 = [[Foo alloc] init]; +id o2 = [[Bar alloc] init]; +id myArray = [[[Array alloc] init] addObjectsCount: 2, o1, o2]; +@end smallexample +@end deftypemethod + +@node Keyed Adding, Indexed Adding, Basic Adding, Adding +@section Keyed Adding + +If the collection's contents are accessible by a key, members can be +inserted at a specified key. See KeyedCollecting protocol. + +@deftypemethod KeyedCollection {} @keyword{-insertObject:} @var{newContentObject} @keyword{atKey:} (elt)@var{aKey} +@deftypemethodx KeyedCollection {} @keyword{-insertElement:} (elt)@var{newContentElement} @keyword{atKey:} (elt)@var{aKey} +<> returns self. +@end deftypemethod + +@node Indexed Adding, , Keyed Adding, Adding +@section Indexed Adding + +Furthermore, if the collections contents are accessible by an index (an +unsigned integer key), members can be appended, prepended. Inserted +members push other members down to make room. +See IndexedCollecting protocol. + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{atIndex:} (unsigned)@var{index} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{atIndex:} (unsigned)@var{index} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{before:} @var{oldObject} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{before:} @var{oldObject} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-insertObject:} @var{newObject} @keyword{after:} @var{oldObject} +@deftypemethodx IndexedCollecting {} @keyword{-insertElement:} (elt)@var{newElement} @keyword{after:} @var{oldObject} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{insertContentsOf:} (id )@var{aCollection} @keyword{atIndex:} (unsigned)@var{index} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-appendObject:} @var{newObject} +@deftypemethodx IndexedCollecting {} @keyword{-appendElement:} (elt)@var{newElement} +@deftypemethodx IndexedCollection {} @keyword{-prependObject:} @var{newObject} +@deftypemethodx IndexedCollecting {} @keyword{-prependElement:} (elt)@var{newElement} +<> returns self. +@end deftypemethod + +@deftypemethod IndexedCollection {} @keyword{-appendContentsOf:} (id )@var{aCollection} +@deftypemethodx IndexedCollection {} @keyword{-prependContentsOf:} (id )@var{aCollection} +<> returns self. +@end deftypemethod + +<> + + +@node Removing, Replacing, Adding, Top +@chapter Removing Elements from a Collection + +About removing... + +@menu +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +@end menu + +@node Basic Removing, Keyed Removing, , Removing + +@node Keyed Removing, Indexed Removing, Basic Removing, Removing + +@node Indexed Removing, , Keyed Removing, Removing + + +<> + +@node Replacing, Enumerating, Removing, Top +@chapter Replacing Elements in a Collection + +@menu +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +@end menu + +@node Basic Replacing, Keyed Replacing, , Replacing + +@node Keyed Replacing, Indexed Replacing, Basic Replacing, Replacing + +@node Indexed Replacing, , Keyed Replacing, Replacing + +<> + + +@node Enumerating, Duplicating, Replacing, Top +@chapter Enumerating the Contents of a Collection + +Enumeration methods allow you to perform a specified operation on the +members of a collection. You can operate on all the members, operate on +all the members until a flag is set, operate only on the members that +pass some test, or operate on the results of passing the members through +a modifying function. Each of the enumerators come in pairs: one method +for enumerating in place, and another method that is ``safe'' for +enumerating when the operation changes the contents of the receiving +collection. If the contents of the collection are changed during the +enumeration you must use the ``safe'' methods. + +@menu +* Safe vs Unsafe Enumerating:: Enumerations while changing the contents + +* Basic Enumerating:: Enumerations available for all collections +* Keyed Enumerating:: Enumerations on collections with keys +* Indexed Enumerating:: Enumerations on ordered collections + +* LAMBDA:: Defining functions in place with LAMBDA() +@end menu + +@node Safe vs Unsafe Enumerating, Basic Enumerating, , Enumerating +@section Safe vs Unsafe Enumerating + +The simple enumerators operate on the collection in-place. If the +contents of the collection change during the enumeration, you must use +the ``safe'' version of the enumerator instead. + +It works by making a shallow copy of the receiver, performing the +enumeration using the shallow copy, then freeing the shallow copy. + +All enumerators have both ``safe'' and plain versions. + +<> + +@node Basic Enumerating, Keyed Enumerating, Safe vs Unsafe Enumerating, Enumerating +@section Basic Enumerating + +The most basic enumerator is +@deftypemethod Collection {} @keyword{-withObjectsCall:} (void(*)(id))@var{func} +@deftypemethodx Collection {} @keyword{-safeWithObjectsCall:} (void(*)(id))@var{func} +@deftypemethodx Collection {} @keyword{-withElementsCall:} (void(*)(elt))@var{func} +@deftypemethodx Collection {} @keyword{-safeWithElementsCall:} (void(*)(elt))@var{func} +Calls the function @var{func} with each the members of the collection. +Returns self. +@end deftypemethod + +@deftypemethod {Collection} {(void*)} -newEnumState +@end deftypemethod + +@deftypemethod {Collection} {} -freeEnumState: (void**)@var{enumStatePtr} +@end deftypemethod + +@deftypemethod {Collection} {(BOOL)} -getNextObject: (id *)@var{anObjectPtr} @keyword{withEnumState:} (void**)@var{enumState} +@deftypemethodx {Collection} {(BOOL)} -getNextElement: (elt *)@var{anElementPtr} @keyword{withEnumState:} (void**)@var{enumState} +@refill +@end deftypemethod + +@example +void print_first_difference (id coll1, id coll2) + @{ + void *enumState1, *enumState2; + id object1, object2; + + enumState1 = [coll1 newEnumState]; + enumState2 = [coll2 newEnumState]; + while ([coll1 getNextObject:&object1 withEnumState:&enumState1] + && [coll2 getNextObject:&object2 withEnumState:&enumState2]) + @{ + if ([object1 compare:object2]) + @{ + [object1 printForDebugger]; + [object2 printForDebugger]; + @} + @} + [coll1 freeEnumState:&enumState1]; + [coll2 freeEnumState:&enumState2]; + @} +@end example + +@deftypemethod {Collection} {} -withElementsCall: (void(*)(elt))@var{aFunc} @keyword{whileTrue:} (BOOL*)@var{flag} +@deftypemethodx {Collection} {} -safeWithElementsCall: (void(*)(elt))@var{aFunc} @keyword{whileTrue:} (BOOL*)@var{flag} +@refill +@end deftypemethod + + +@node Keyed Enumerating, Indexed Enumerating, Basic Enumerating, Enumerating +@section Keyed Enumerating + + +@node Indexed Enumerating, LAMBDA, Keyed Enumerating, Enumerating +@section Indexed Enumerating + +@deftypemethod {IndexedCollection} {(BOOL)} -getPrevObject: (id *) @var{anObjectPtr} @keyword{withEnumState:} (void**)@var{enumState} +@deftypemethodx {IndexedCollection} {(BOOL)} -getPrevElement: (elt *) @var{anElementPtr} @keyword{withEnumState:} (void**)@var{enumState} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -withObjectsInReverseCall: (void(*)(id))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -safeWithObjectsInReverseCall: (void(*)(id))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -withElementsInReverseCall: (void(*)(elt))@var{aFunc} +@deftypemethodx {IndexedCollection} {} -safeWithElementsInReverseCall: (void(*)(elt))@var{aFunc} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -withObjectsInReverseCall: (void(*)(id)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -safeWithObjectsInReverseCall: (void(*)(id)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -withElementsInReverseCall: (void(*)(elt)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@deftypemethodx {IndexedCollection} {} -safeWithElementsInReverseCall: (void(*)(elt)) @var{aFunc} @keyword{whileTrue:} (BOOL *)@var{flag} +@refill +@end deftypemethod + +@deftypemethod {IndexedCollection} {} -makeObjectsPerformInReverse: (SEL) @var{aSel} +@deftypemethodx {IndexedCollection} {} -safeMakeObjectsPerformInReverse: (SEL) @var{aSel} +@deftypemethodx {IndexedCollection} {} -makeObjectsPerformInReverse: (SEL) @var{aSel} @keyword{with:} @var{argObject} +@deftypemethodx {IndexedCollection} {} -safeMakeObjectsPerformInReverse: (SEL) @var{aSel} @keyword{with:} @var{argObject} +@refill +@end deftypemethod + + +@node LAMBDA, , Indexed Enumerating, Enumerating +@section Defining Functions In Place with LAMBDA() +@cindex Defining Functions In Place +@cindex Function definitions with LAMBDA + +NOTE: The LAMBDA macro does not work on all systems. We are waiting +for a general fix. You should avoid using it until then. + +There may not already be a function that does the operation you want +performed during an enumeration. In this case you will have to +write such a function yourself. + +If the function will be used more than once, you should write it as C +functions are usually defined. However, if the function will only be +used for this one enumeration and the function is small, using the +@code{LAMBDA} macro may be easier and more clear. + +@defmac LAMBDA(@var{RETTYPE}, @var{ARGS}, @var{BODY}) +@code{LAMBDA} is a macro for defining a nested function and returning +a pointer to that function. You can use @code{LAMBDA} wherever a +function pointer is required. @var{RETTYPE} is the C type returned by +the function. @var{ARGS} is the parenthesis-enclosed list of arguments +to the function. (Declare them just like in an ANSI function +definition.) @var{BODY} is the curly-bracket-enclosed body of the +function. + +For example, you could create a pointer to a function that adds its +arguments like this: +@smallexample +LAMBDA(int, (int a, int b), @{return a + b;@}) +@end smallexample +@end defmac + +@code{LAMBDA} is particularly convenient for enumeration methods because +the macro can be placed in the position of the method argument. For +instance, you can write: +@example + - fooMethod + @{ + id newColl; + ... + newColl = [self emptyCopyAs:[Array class]]; + [self withObjectsCall: + LAMBDA(void, (id o), @{[newColl addObject:[o copy]];@})]; + return self; + @} +@end example +instead of writing: +@smallexample + - fooMethod + @{ + id newColl = [self emptyCopyAs:[Array class]]; + void myTmpFunc(id o) + @{ + [newColl addObject:[o copy]]; + @} + ... + [self withObjectsCall:myTmpFunc]; + return self; + @} +@end smallexample +In these examples, there may be many lines of code between the +declarations at the top of the method and the @code{withObjectsCall:} at +the bottom of the method. Using @code{LAMBDA} allows you to declare +the function where it is used, instead of arbitrarily far from where it +is used. + +The name @code{LAMBDA} comes from lambda calculus and LISP. + +The @code{LAMBDA} macro and some similar macros are defined in +@samp{coll/collstd.h}. + +@section Filtered Enumerating + +@section Enumerating with Keyed Collections + +@section Enumerating with Indexed Collections + +<> + + +@node Duplicating, Archiving, Enumerating, Top +@chapter Duplicating + +Talk about shallow and deep copies. + +<> + + +@node Archiving, Querying, Duplicating, Top +@chapter Archiving + +You can write collections to a stream. You can read them back in again. +Talk about the @code{-awake} method. + +@deftypemethod Collection {} @keyword{-write:} (TypedStream*)@var{aStream} +<> Returns self. +@end deftypemethod + +@deftypemethod Collection {} @keyword{-read:} (TypedStream*)@var{aStream} +<> Returns self. +@end deftypemethod + +<> + + +@node Querying, Sorting, Archiving, Top +@chapter Querying + +<> + +@menu +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Basic Querying, Keyed Querying, , Querying +@section Basic Querying + +@deftypemethod Collection {(BOOL)} @keyword{-isEmpty} +Returns YES if the receiver contains no members; returns NO otherwise. +@end deftypemethod + +@deftypemethod Collection {(const char *)} @keyword{-contentEncoding} +Returns a description of the C type that the receiving collection can +hold. The description is a string of the form returned by the +Objective-C @code{@@encode} directive. +@end deftypemethod + +@node Keyed Querying, Indexed Querying, Basic Querying, Querying +@section Keyed Querying + +@node Indexed Querying, , Keyed Querying, Querying +@section Indexed Querying + +@node Sorting, Classes, Querying, Top +@chapter Sorting + +<> + + +@node Classes, Projects, Sorting, Top +@chapter Choosing the Right Class + +Talk about keys or no keys, ordered or not ordered. Talk about the +classes the require protocol-conforming objects as members. + +@menu +* Set:: +* Bag:: + +* Dictionary:: +* MappedCollector:: + +* Array:: +* Stack:: +* Queue:: +* GapArray:: + +* LinkedList:: +* BinaryTree:: +* RBTree:: +* SplayTree:: +* EltNodeCollector:: + +* Collection:: +* KeyedCollection:: +* IndexedCollection:: +@end menu + +<> + +@node Set, Bag, , Classes +@section Set + +<> + +@node Bag, Dictionary, Set, Classes +@section Bag + +A Bag is ... + +@menu +* Basic Creating:: +* Freeing:: +* Bag Adding:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Bag Removing:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: + + +@end menu + +@node Bag Adding, Bag Removing, , Bag + +@deftypemethod Bag {} @keyword{-addObject:} @var{newObject} withOccurrences: (unsigned)@var{count} +@deftypemethodx Bag {} @keyword{-addElement:} (elt)@var{newElement} withOccurrences: (unsigned)@var{count} +@end deftypemethod + +@node Bag Removing, , Bag Adding, Bag + +@deftypemethod Bag {} @keyword{-removeObject:} @var{oldObject} occurrences: (unsigned)@var{count} +@deftypemethodx Bag {} @keyword{-removeElement:} (elt)@var{oldElement} occurrences: (unsigned)@var{count} +@end deftypemethod + +<> + +@node Dictionary, MappedCollector, Bag, Classes +@section Dictionary + +A Dictionary is ... + +@node MappedCollector, Array, Dictionary, Classes +@section MappedCollector + +A MappedCollector is ... + +@node Array, Stack, MappedCollector, Classes +@section Array + +An Array is ... + +@menu +* Array Capacity Management:: +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Array Capacity Management, , , Array +@section Array Methods + +@deftypemethod {Array} {(unsigned)} @keyword{+defaultCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {(unsigned)} @keyword{+defaultGrowFactor} +@refill +@end deftypemethod + +@deftypemethod {Array} {} @keyword{-initEncoding:} (const char *) +@var{contentEncoding} @keyword{capacity:} (unsigned) @var{aCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {} -setCapacity: (unsigned) @var{newCapacity} +@refill +@end deftypemethod + +@deftypemethod {Array} {} -setGrowFactor: (unsigned) @var{aNum} +@refill +@end deftypemethod + +@node Stack, Queue, Array, Classes +@section Stack + +@menu +* Stack Methods:: +* Array Capacity Management:: +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + +@node Stack Methods, , , Stack + +@deftypemethod {Stack} {} -pushObject: @var{newObject} +@deftypemethodx {Stack} {} -pushElement: (elt)@var{newElement} +@end deftypemethod + +@deftypemethod {Stack} {} -popObject: @var{newObject} +@deftypemethodx {Stack} {} -popElement: (elt)@var{newElement} +@end deftypemethod + +@deftypemethod {Stack} {} -topObject +@deftypemethodx {Stack} {(elt)} -topElement +@end deftypemethod + +@deftypemethod {Stack} {} -exchangeTop +@end deftypemethod + +@node Queue, GapArray, Stack, Classes + +@node GapArray, LinkedList, Queue, Classes + +@node LinkedList, BinaryTree, GapArray, Classes + +@node BinaryTree, RBTree, LinkedList, Classes + +@node RBTree, SplayTree, BinaryTree, Classes + +@node SplayTree, EltNodeCollector, RBTree, Classes + +@node EltNodeCollector, Collection, SplayTree, Classes + +@node Collection, KeyedCollection, EltNodeCollector, Classes + +A Collection is ... + +@menu +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Basic Removing:: +* Basic Replacing:: +* Basic Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +@end menu + +@node KeyedCollection, IndexedCollection, Collection, Classes +@section KeyedCollection + +@menu +* Basic Creating:: +* Keyed Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +@end menu + +@node IndexedCollection, , KeyedCollection, Classes +@section IndexedCollection + +@menu +* Basic Creating:: +* Freeing:: +* Basic Adding:: +* Keyed Adding:: +* Indexed Adding:: +* Basic Removing:: +* Keyed Removing:: +* Indexed Removing:: +* Basic Replacing:: +* Keyed Replacing:: +* Indexed Replacing:: +* Basic Enumerating:: +* Keyed Enumerating:: +* Indexed Enumerating:: +* Duplicating:: +* Archiving:: +* Basic Querying:: +* Keyed Querying:: +* Indexed Querying:: +@end menu + + +@node Projects, Protocol Index, Classes, Top +@chapter To Do List and Questions + +@include todo.texi + +@section How to contribute + +Programmers who have written Objective-C classes that they believe to be +of general interest are encouraged to write to +mccallum@@gnu.ai.mit.edu. Contributing code is not difficult. Here are +some general guidelines: + +@itemize @bullet + +@item +FSF must maintain the right to accept or reject potential contributions. +Generally, the only reasons for rejecting contributions are cases where +they duplicate existing or nearly-released code, contain unremovable +specific machine dependencies, or are somehow incompatible with the +rest of the library. + +@item +Acceptance of contributions means that the code is accepted for adaptation +into libobjects. FSF must reserve the right to make various editorial changes +in code. Very often, this merely entails formatting, maintenance of various +conventions, etc. Contributors are always given authorship credit and shown +the final version for approval. + +@item +Contributors must assign their copyright to FSF via a form sent out +upon acceptance. Assigning copyright to FSF ensures that the code +may be freely distributed. + +@item +Assistance in providing documentation, test files, and debugging +support is strongly encouraged. + +@end itemize + +Extensions, comments, and suggested modifications of existing libobjects +features are also very welcome. + +@node Protocol Index, Class Index, Projects, Top +@unnumbered Protocol Index +@printindex pr + + +@node Class Index, Method Function Macro Index, Protocol Index, Top +@unnumbered Class Index +@printindex cl + + +@node Method Function Macro Index, Concept Index, Class Index, Top +@unnumbered Method, Function and Macro Index +@printindex fn + +@node Concept Index, , Method Function Macro Index, Top +@unnumbered Concept Index +@printindex cp + +@summarycontents +@contents + +@bye diff --git a/Documentation/news.texi b/Documentation/news.texi new file mode 100644 index 000000000..72bdd9e74 --- /dev/null +++ b/Documentation/news.texi @@ -0,0 +1,131 @@ +@ifset NEWS_ONLY +@chapter News about GNU Objective C Class Library +@end ifset +@include version.texi + +@section Noteworthy changes in version @samp{0.1} + +@itemize + +@item Renamed the library from @samp{libcoll} to @samp{libobjects}. +(See the end of the file @samp{DISCUSSION} for the background on this +name choice.) Several file names changed to reflect this. GNU class +interfaces are now included with @samp{objects} prefix, +e.g. @samp{#include }. + +@item Many new classes. Pseudo-random number classes Random, RNGBerkeley +and RNGAdditiveCongruential. New stream classes Stream, StdioStream and +MemoryStream. New coder classes Coder, TextCoder and BinaryCoder. New +network packet transmission classes Port and SocketPort. New remote +object messaging classes Connection, Proxy and ConnectedCoder. New +protocols Coding and Retaining. New, but unimplemented: Lock and +Locking. New but soon-to-disapppear: RetainingNotifier, +InvalidationListening. + +@item Some bug fixes: Fixed the assert typo in Storage.m. The Time +class now compiles under Solaris. Fixed insertion bug in CircularArray. +NXStringTable_scan.l can now be compiled with lex, not just flex, +(thanks to Adam Fedor ). Properly detect the +difference between gcc running under NEXTSTEP and NeXT's cc. Using +autoconf version 2.0. Renamed DelegateList to DelegatePool. Renamed +some collection hierarchy methods for better consistency. + +@item Some directory reorganization so that NeXT-compatible files can be +included in the standard way, e.g. #include . Some other +NeXT-compatibility improvements: Changed @samp{GNU} prefix to @samp{NX} +in List and HashTable. New files zone.[hc] containing dummy stubs for +NeXT-compatible zone functions. + +@end itemize + +@c ==================================================================== +@c Keep the next line just below the list of changes in most recent version. +@ifclear ANNOUNCE_ONLY + +@section Noteworthy changes in verion @samp{940524} + +@itemize + +@item A NeXT-compatible NXStringTable object, thanks to Adam Fedor +. + +@item +SplayTree and RBTree classes now operational. More methods in Time +class implemented. + +@item +Some API cleanup: -delegateListList changed to -delegateListCollection. +-includesSameContents: changed to -contentsEqual:. -insertObject:atKey: +changed to -putObject:atKey:. See the ChangeLog for more detail. + +@item +Configuration by autoconf in the self-tests directory. Configuration +script tests GCC nested functions. Configuration script detects +NEXTSTEP and makes the appropriate adjustments, including skipping the +NeXT-compatibility classes. + +@item +Bug fixes: BinaryTree rotate methods fixed. Fixed the way +@code{ifNone:} and @code{ifAbsent:} functions were called. Fixed the +way long elements are printed. Added methods for preventing memory +leaks by unfinished enumerations: @code{-newEnumState} and +@code{-freeEnumState:}. Several bug fixes in List and Storage; changes +for better NeXT-compability. And more. + +@end itemize + +@section Noteworthy changes in version @samp{931026} + +@itemize + +@item +Installation using @samp{./configure} and @samp{autoconf} + +@item +New BinaryTree and RBTree(unfinished) classes. Rewritten LinkedList +class. + +@item +A new scheme for holding non-object elements in classes that require + object contents; EltNodeCollector class. + +@item +Archiving with -write: and -read: methods. This involved removing the +ability to set the comparison function independent of content type. + +@item +Removed COLL_NO_ELEMENT and friends. Now there are no arbitrary +restrictions on which long int's can be stored. Like in Smalltalk, +...ifAbsentCall: methods have been added to replace this functionalty. + +@item +Added a LABMDA() macro for defining small functions in the arg position. + +@item +Removed many ...perform: methods. Use instead the more flexible +...call: methods with LABMDA(). + +@item +Renamed ...Description: methods to ...Encoding: for better use of +already-defined objc keyword: @@encode(). + +@item +New in the Collecting protocol: +Filtered enumerating instead of filtered shallowCopy'ing. +Enumerations still safe when modifying the contents. + +@item +The beginnings of documentation in libcoll.texi. + +@item +Many bug fixes. + +@item +...and more. + +@end itemize + +Also see the @samp{ChangeLog} file for more detail. + +@end ifclear +@c end ifclear ANNOUNCE_ONLY diff --git a/Documentation/readme.texi b/Documentation/readme.texi new file mode 100644 index 000000000..bd56ffe19 --- /dev/null +++ b/Documentation/readme.texi @@ -0,0 +1,337 @@ +@chapter GNU Objective-C Class Library README + +@c set the vars OBJECTS_VERSION and GCC_VERSION +@include version.texi + +Here is some introductory info to get you started: + +@section Initial reading + +The file @samp{ANNOUNCE} contains a very brief overview of the library. +It also tells you where to get the most recent version. + +The file @samp{NEWS} has the library's feature history. + +The file @samp{INSTALL} gives instructions for installing the library. + +The file @samp{DISCUSSION} contains the archives of email discussions +about the library. It's a good place to read about the reasons for +some of the design decisions. + +@section Preparing to write code + +@ignore +Preliminary documentation is available via @samp{texinfo} in the files +@samp{libobjects.info} and @samp{libobjects.texi}. The info file was +created from the texi file using an modified version of @samp{makeinfo} +available by anonymous ftp from @samp{iesd.auc.dk:pub/ObjC}. +@end ignore + +The documentation isn't much to speak of so far. Better documentation +will be forthcoming, but the library needs to settle first. For now I +recommend skipping libobjects.info and reading the header files +instead. The headers for the GNU classes are in ./objects; the headers +for the NeXT-compatible classes are in ./objects/next-include. + +[NOTE: To compile code that uses NeXT compatibility classes, you'll want +to put @samp{XX/objects/next-include} in your include file search path. +Then, (unlike with the old libcoll), you can use #include +instead of #include .] + +The overview of classes below should help you see the big picture as you +read the source. + + +@section The Class Heirarchy + +Here is the class inheritance heirarchy. All protocols end with +"ing"; all collection protocols end with "Collecting". All collection +abtract superclasses (classes which are not usable without +subclassing) end with "Collection"; + +@example + Collection + Set + Bag + KeyedCollection + Dictionary + MappedCollector + IndexedCollection + Array + Stack + GapArray + CircularArray + Queue + Heap + LinkedList + BinaryTree + RBTree + EltNodeCollector + String + DelegatePool + LinkedListNode + LinkedListEltNode + BinaryTreeNode + BinaryTreeEltNode + RBTreeNode + RBTreeEltNode + Stream + StdioStream + MemoryStream + Coder + TextCoder + BinaryCoder + ConnectedCoder + Port + SocketPort + Connection + Proxy + Magnitude + Time + Random + RNGBerkeley + RNGAdditiveCongruential +@end example + + +@section Overview of the classes + +The GNU classes included in this version of the library fall into five +categories: collections, magnitudes, streams, coders and distributed +object support. + +@c There are several GNU protocols also. You can recognize the protocols +@c by their name: they all end with ``ing''. + +@itemize + +@item The collection objects all conform to the @samp{Collecting} +protocol. Reading @samp{./objects/Collecting.h} is a good place to +start. Protocols for collections that store their contents with keys +and with indices can be found in @samp{./objects/KeyedCollecting.h} and +@samp{./objects/IndexedCollecting.h} respectively. Examples of generic +collections are @samp{Set} and @samp{Bag}. The keyed collections are +@samp{Dictionary} and @samp{MappedCollector}. The classes @samp{Array}, +@samp{Queue}, @samp{GapArray}, @samp{LinkedList}, @samp{BinaryTree}, +@samp{RBTree} and @samp{SplayTree} are all indexed collections. + +@item The public magnitude classes are @samp{Time} and @samp{Random}. +The @samp{Random} class works in conjunction with pseudo-random number +generators that conform to the @samp{RandomGenerating} protocol. The +conforming class @samp{RNGBerkeley} provides identical behavior to the +BSD random() function. The class @samp{RNGAdditiveCongruential} is an +implementation of the additive congruential method. + +@item Stream objects provide a consistent interface for reading and +writing bytes. Read @samp{./objects/Stream.h} to get the general idea. +@samp{StdioStream} objects work with files, file descriptors, FILE +pointers and pipes to/from executables. @samp{MemoryStream} objects +work with memory buffers. + +@item Coders provide a formatted way of writing to Streams. After a +coder is initialized with a stream, the coder can encode/decode +Objective C objects and C types in an architecture-independent way. See +@samp{./objects/Coder.h} for the abstract superclass interface; see +@samp{./objects/Coding.h} for the protocol adopted by objects that read +and write themselves using coders. The currently available concrete +coder classes are @samp{BinaryCoder}, for reading and writing a compact +stream of illegible bytes, and @samp{TextCoder}, for reading and writing +human-readable text (which you can also process with @samp{perl}, +@samp{awk}, or whatever scripting language you like). + +Coders and streams can be mixed and matched so that programmers can +choose the destination and the format separately. + +Neither the stream or coder class heirarchies are very mature yet. I +threw them together because I needed them for distributed objects. + +@item The distributed object support classes are @samp{Connection}, +@samp{Proxy}, @samp{ConnectedCoder}, @samp{Port} and @samp{SocketPort}. +This version of the distributed objects only works with sockets. A Mach +port back-end should be on the way. + +[NOTE: The GNU distributed object facilities have the same ease-of-use +as NeXT's; be warned, however, that they are not compatible with each +other. They have different class heirarchies, different instance +variables, different method names, different implementation strategies +and different network message formats. You cannot communicate with a +NeXT NXConnection using a GNU Connection. The GNU distributed object +code does not work with the NeXT Objective C runtime. NXConnection +creates NXProxy objects for local objects as well as remote objects; GNU +Connection doesn't need and doesn't create proxies for local objects. +NXProxy asks it's remote target for the method encoding types and caches +the results; GNU Proxy gets the types directly from the local GNU "typed +selector" mechanism and has no need for querying the remote target or +caching encoding types. The NXProxy for the remote root object always +has name 0 and, once set, you cannot change the root object of a +NXConnection; the GNU Proxy for the remote root object has a target +address value just like all other Proxy's, and you can change the root +object as many times as you like. See the "lacking-capabilities" list +below for a partial list of things that NXConnection can do that GNU +Connection cannot.] + +To begin using distributed objects, you only need to know about +@samp{Connection} class. You can see the full interface in +@samp{./objects/Connection.h}. The long list of methods may be a little +daunting, but actually, a lot can be done with just a few key methods: + +@smallexample +- (Connection*) newRegisteringAtName: (const char*)name + withRootObject: anObj; + For registering your server object with the network. + +- (void) runConnection; + For running the connection object returned by the above + method, so that your server can start handling requests from + clients. + +- (Proxy*) rootProxyAtName: (const char*)name + onHost: (const char*)host; + For connecting to a remote server. You get a proxy object for + the remote server object, which, for messaging purposes, you + can treat as if it were local. +@end smallexample + +Here is a partial list of what the current distributed objects system +can do: +@smallexample +- It can pass and return all simple C types, including char*, float + and double, both by value and by reference. +- It can pass structures by value and by reference, return + structures by reference. The structures can contain arrays. +- It obeys all the type qualifiers: oneway, in, out, inout, const. +- It can pass and return objects, either bycopy or with proxies. + An object encoded multiple times in a single message is properly + decoded on the other side. +- Proxies to remote objects are automatically created as they are + returned. Proxies passed back where they came from are decoded + as the correct local object. +- It can wait for an incoming message and timeout after a + specified period. +- A server can handle multiple clients. +- The server will ask its delegate before making new connections. +- The server can make call-back requests of the client, and keep + it all straight even when the server has multiple clients. +- A client will automatically form a connection to another client + if an object from the other client is vended to it. (i.e. Always + make a direct connection rather than forwarding messages twice, + once into the server, from there out to the other client.) +- The server will clean up its connection to a client if the client + says goodbye (i.e. if the client connection is freed). +- When the connection is being freed it will send a invalidation + notification message to those objects that have registered for + such notification. +- Servers and clients can be on different machines of different + architectures; byte-order and all other architecture-dependent + nits are taken care of for you. You can have SPARC, i386, m68k, + and MIPS machines all distributed-object'ing away together in + one big web of client-server connections! +@end smallexample + +Here is a partial list of what the current distributed objects system +does *not* do: +@smallexample +- Run multi-threaded. +- Detect port deaths (due to remote application crash, for example) + and do something graceful. +- Send exceptions in the server back to the client. +- Send messages with vararg arguments. +- Return structures by value. +- Use Mach ports, pass Mach ports, pass Mach virtual memory. +- Send messages more reliably than UDP. It does detect reply + timeouts and message-out-of-order conditions, but it's reaction + is simply to abort. +- Claim to be thoroughly tested. +@end smallexample + +@end itemize + + +@section Where else to look + +@subsection Examples + +A few simple example programs can be found in @samp{./examples}. +Read and enjoy. To compile them (after having compiled the library), +type @samp{make} in the @samp{examples} directory. + +@itemize + +@item @samp{dictionary.m} demonstrates the basic features of the +Dictionary object. + +@item @samp{stdio-stream.m} creates a StdioStream object that points to +a file, writes to the file, then reads from the file. + +@item @samp{textcoding.m} shows how you can archive an object to a file +in a human-readable text format, and then read it back in again. This +format is handy for editing archived objects with a text editor, and is +great when you want to modify/create an archive using a scripting +language like @samp{perl} or @samp{awk}. + +@item @samp{first-server.m} and @samp{first-client.m} show the +distributed object version of ``Hello, world''. + +@item @samp{second-server.m} and @samp{second-client.m} contain a more +complex demonstration of distributed objects, with multiple clients, +connection delegates, and invalidation notification. + +@item @samp{port-server.m} and @samp{port-client.m} show a simple use of +Port objects. Be warned, however, the interface to Port objects will +likely change in the near future. + +@end itemize + +@subsection Test Programs + +Some of the programs I've used to test the library are in +@samp{./checks}. Many of them are pretty messy, (desperately trying to +tickle that late night bug), but at least they show some code that works +when the library compiles correctly. I'm looking for a volunteer to +write some nicely organized test cases using @samp{dejagnu}. Any +takers? + + +@section Coming Soon... + +More improvements to the library are on the way. Closest in the +pipeline are String objects and better allocation/deallocation +conventions for objects. + +These improvements will bring some changes to the current interfaces: +(1) Almost everywhere that the current methods now take (char*) +arguments, the new methods will take (String*) arguments. (2) The use +of the method @samp{free} will be abolished and replaced by new +methods. + +I'm trying to get these changes in place as soon as possible so that +you don't end up writing too much code that uses the old (i.e. current) +interfaces. + +Meanwhile, please use the library! The small amount of changes you may +need to make won't be difficult, and the earlier I get usability +suggestions and bug reports, the sooner the fixes will come. + + +@section How can you help? + +@itemize + +@item Read the projects and questions in the @samp{TODO} file. If you +have any useful comments mail them to me! + +@item +Give me feedback! Tell me what you like; tell me what you think +could be better. Send me bug reports. + +@item +Donate classes. If you write classes that fit in the libobjects +framework, I'd be happy to include them. + +@end itemize + +@example +Happy hacking! + Andrew McCallum + mccallum@@gnu.ai.mit.edu +@end example diff --git a/Documentation/texinfo.tex b/Documentation/texinfo.tex new file mode 100644 index 000000000..e36b010a2 --- /dev/null +++ b/Documentation/texinfo.tex @@ -0,0 +1,4030 @@ +%% texinfo.tex with patches to handle `deftypemethod' +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc. + +%This texinfo.tex file is free software; you can redistribute it and/or +%modify it under the terms of the GNU General Public License as +%published by the Free Software Foundation; either version 2, or (at +%your option) any later version. + +%This texinfo.tex file is distributed in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%General Public License for more details. + +%You should have received a copy of the GNU General Public License +%along with this texinfo.tex file; see the file COPYING. If not, write +%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, +%USA. + + +%In other words, you are welcome to use, share and improve this program. +%You are forbidden to forbid anyone else to use, share and improve +%what you give them. Help stamp out software-hoarding! + +\def\texinfoversion{2.108} +\message{Loading texinfo package [Version \texinfoversion]:} + +% Print the version number if in a .fmt file. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{}} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +\def\tie{\penalty 10000\ } % Save plain tex definition of ~. + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +%---------------------Begin change----------------------- +% +%%%% For @cropmarks command. +% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen \topandbottommargin +\newdimen \outerhsize \newdimen \outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in +% +%---------------------End change----------------------- + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions itself, but you have to call it yourself. +\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} +\def\onepageout#1{\hoffset=\normaloffset +\ifodd\pageno \advance\hoffset by \bindingoffset +\else \advance\hoffset by -\bindingoffset\fi +{\escapechar=`\\\relax % makes sure backslash is used in output files. +\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}% +{\let\hsize=\pagewidth \makefootline}}}% +\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi} + +%%%% For @cropmarks command %%%% + +% Here is a modification of the main output routine for Near East Publications +% This provides right-angle cropmarks at all four corners. +% The contents of the page are centerlined into the cropmarks, +% and any desired binding offset is added as an \hskip on either +% site of the centerlined box. (P. A. MacKay, 12 November, 1986) +% +\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up +{\escapechar=`\\\relax % makes sure backslash is used in output files. + \shipout + \vbox to \outervsize{\hsize=\outerhsize + \vbox{\line{\ewtop\hfill\ewtop}} + \nointerlineskip + \line{\vbox{\moveleft\cornerthick\nstop} + \hfill + \vbox{\moveright\cornerthick\nstop}} + \vskip \topandbottommargin + \centerline{\ifodd\pageno\hskip\bindingoffset\fi + \vbox{ + {\let\hsize=\pagewidth \makeheadline} + \pagebody{#1} + {\let\hsize=\pagewidth \makefootline}} + \ifodd\pageno\else\hskip\bindingoffset\fi} + \vskip \topandbottommargin plus1fill minus1fill + \boxmaxdepth\cornerthick + \line{\vbox{\moveleft\cornerthick\nsbot} + \hfill + \vbox{\moveright\cornerthick\nsbot}} + \nointerlineskip + \vbox{\line{\ewbot\hfill\ewbot}} + }} + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi} +% +% Do @cropmarks to get crop marks +\def\cropmarks{\let\onepageout=\croppageout } + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = \baselineskip +\def\singlespace{% +% Why was this kern here? It messes up equalizing space above and below +% environments. --karl, 6may93 +%{\advance \baselineskip by -\singlespaceskip +%\kern \baselineskip}% +\baselineskip=\singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt \char '100}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. + +\def\mylbrace {{\tt \char '173}} +\def\myrbrace {{\tt \char '175}} +\let\{=\mylbrace +\let\}=\myrbrace + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % We do @comment here in case we are called inside an environment, + % such as @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output some dots + +\def\dots{$\ldots$} + +% @page forces the start of a new page + +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. + +\def\include{\parsearg\includezzz} +%Use \input\thisfile to avoid blank after \input, which may be an active +%char (in which case the blank would become the \input argument). +%The grouping keeps the value of \thisfile correct even when @include +%is nested. +\def\includezzz #1{\begingroup +\def\thisfile{#1}\input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\par \vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + \long\def\doignoretext##1\end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}} +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% +\def\set{\parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi +} +\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex always succeeds; we read the text following, through @end +% iftex). But `@end iftex' should be valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\defineunmatchedend{iftex} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\let\lastnode=\relax} + +\let\refill=\relax + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \readauxfile + \opencontents + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + \comment % Ignore the actual filename. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\font\textrm=cmr12 +\font\texttt=cmtt12 +\else +\font\textrm=cmr10 scaled \mainmagstep +\font\texttt=cmtt10 scaled \mainmagstep +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\font\textbf=cmb10 scaled \mainmagstep +\font\textit=cmti10 scaled \mainmagstep +\font\textsl=cmsl10 scaled \mainmagstep +\font\textsf=cmss10 scaled \mainmagstep +\font\textsc=cmcsc10 scaled \mainmagstep +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\font\defbf=cmbx10 scaled \magstep1 %was 1314 +\font\deftt=cmtt10 scaled \magstep1 +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\font\ninett=cmtt9 +\font\indrm=cmr9 +\font\indit=cmsl9 +\let\indsl=\indit +\let\indtt=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\let\indsc=\indrm +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for headings +\font\chaprm=cmbx12 scaled \magstep2 +\font\chapit=cmti12 scaled \magstep2 +\font\chapsl=cmsl12 scaled \magstep2 +\font\chaptt=cmtt12 scaled \magstep2 +\font\chapsf=cmss12 scaled \magstep2 +\let\chapbf=\chaprm +\font\chapsc=cmcsc10 scaled\magstep3 +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +\font\secrm=cmbx12 scaled \magstep1 +\font\secit=cmti12 scaled \magstep1 +\font\secsl=cmsl12 scaled \magstep1 +\font\sectt=cmtt12 scaled \magstep1 +\font\secsf=cmss12 scaled \magstep1 +\font\secbf=cmbx12 scaled \magstep1 +\font\secsc=cmcsc10 scaled\magstep2 +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad. +% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded. +% \font\ssecsl=cmsl10 scaled \magstep1 +% \font\ssectt=cmtt10 scaled \magstep1 +% \font\ssecsf=cmss10 scaled \magstep1 + +%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx. +%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than +%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1. +%\font\ssectt=cmtt10 scaled 1315 +%\font\ssecsf=cmss10 scaled 1315 + +%\let\ssecbf=\ssecrm + +\font\ssecrm=cmbx12 scaled \magstephalf +\font\ssecit=cmti12 scaled \magstephalf +\font\ssecsl=cmsl12 scaled \magstephalf +\font\ssectt=cmtt12 scaled \magstephalf +\font\ssecsf=cmss12 scaled \magstephalf +\font\ssecbf=cmbx12 scaled \magstephalf +\font\ssecsc=cmcsc10 scaled \magstep1 +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled \magstep1 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% Fonts for title page: +\font\titlerm = cmbx12 scaled \magstep3 +\let\authorrm = \secrm + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current. Plain TeX does, for example, +% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need +% to redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \resetmathfonts} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \resetmathfonts} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \resetmathfonts} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \resetmathfonts} +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy + \resetmathfonts} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\font\shortcontrm=cmr12 +\font\shortcontbf=cmbx12 +\font\shortcontsl=cmsl12 + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \nohyphenation \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont = \t +%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null} +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overful hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate an a dash. +% -- rms. +{ +\catcode `\-=\active +\catcode `\_=\active +\global\def\code{\begingroup \catcode `\-=\active \let-\codedash \let_\codeunder \codex} +} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\normalunderscore\discretionary{}{}{}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else\tclose{\look}\fi +\else\tclose{\look}\fi} + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of +% @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +\def\l#1{{\li #1}\null} % + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\def\titlefont#1{{\titlerm #1}} + +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefont{##1}} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} +\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} +\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\ifcase\month\or +January\or February\or March\or April\or May\or June\or +July\or August\or September\or October\or November\or December\fi +\space\number\year} + +% Use this if you want the Month Day, Year style of output. +%\def\today{\ifcase\month\or +%January\or February\or March\or April\or May\or June\or +%July\or August\or September\or October\or November\or December\fi +%\space\number\day, \number\year} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + +\message{tables,} + +% @tabs -- simple alignment + +% These don't work. For one thing, \+ is defined as outer. +% So these macros cannot even be defined. + +%\def\tabs{\parsearg\tabszzz} +%\def\tabszzz #1{\settabs\+#1\cr} +%\def\tabline{\parsearg\tablinezzz} +%\def\tablinezzz #1{\+#1\cr} +%\def\&{&} + +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\par \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\par \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + {\parskip = 0in + \par + }% + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0 + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}% + \fi + \endgroup +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Neccessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemsize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{\in hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. + +\def\newindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +\def\synindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\char{\realbackslash char}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\copyright{\realbackslash copyright }% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other +@gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. + +\def\doind #1#2{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% Expand all macros now EXCEPT \folio +\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now +% so it will be output as is; and it will print as backslash in the indx. +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}}}% +\temp }% +}\penalty\count10}} + +\def\dosubind #1#2#3{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% +\def\rawbackslashxx{\indexbackslash}% +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2 #3}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% +\temp }% +}\penalty\count10}} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% This is what you call to cause a particular index to get printed. +% Write +% @unnumbered Function Index +% @printindex fn + +\def\printindex{\parsearg\doprintindex} + +\def\doprintindex#1{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other\catcode`\_=\other + \catcode`\~=\other + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \begindoublecolumns + % + % See if the index file exists and is nonempty. + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + (Index is nonexistent) + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + (Index is empty) + \else + \input \jobname.#1s + \fi + \fi + \closein 1 + \enddoublecolumns + \Etex +} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent=2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +%% Define two-column mode, which is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % Grab any single-column material above us. + \output = {\global\setbox\partialpage + =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% + \eject + % + % Now switch to the double-column output routine. + \output={\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it once. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +- < + % 1pt) as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\catcode `\@=\other +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount \chapno +\newcount \secno \secno=0 +\newcount \subsecno \subsecno=0 +\newcount \subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount \appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +\newwrite \contentsfile +% This is called from \setfilename. +\def\opencontents{\openout \contentsfile = \jobname.toc} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\if \pageno<0 % +\errmessage{@#1 not allowed after generating table of contents}\fi +% +} + +\def\chapternofonts{% +\let\rawbackslash=\relax% +\let\frenchspacing=\relax% +\def\result{\realbackslash result} +\def\equiv{\realbackslash equiv} +\def\expansion{\realbackslash expansion} +\def\print{\realbackslash print} +\def\TeX{\realbackslash TeX} +\def\dots{\realbackslash dots} +\def\copyright{\realbackslash copyright} +\def\tt{\realbackslash tt} +\def\bf{\realbackslash bf } +\def\w{\realbackslash w} +\def\less{\realbackslash less} +\def\gtr{\realbackslash gtr} +\def\hat{\realbackslash hat} +\def\char{\realbackslash char} +\def\tclose##1{\realbackslash tclose {##1}} +\def\code##1{\realbackslash code {##1}} +\def\samp##1{\realbackslash samp {##1}} +\def\r##1{\realbackslash r {##1}} +\def\b##1{\realbackslash b {##1}} +\def\key##1{\realbackslash key {##1}} +\def\file##1{\realbackslash file {##1}} +\def\kbd##1{\realbackslash kbd {##1}} +% These are redefined because @smartitalic wouldn't work inside xdef. +\def\i##1{\realbackslash i {##1}} +\def\cite##1{\realbackslash cite {##1}} +\def\var##1{\realbackslash var {##1}} +\def\emph##1{\realbackslash emph {##1}} +\def\dfn##1{\realbackslash dfn {##1}} +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{Chapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{Appendix \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{Appendix \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the to achieve this: TeX expands \the only once, +% simply yielding the contents of the . +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appenixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry % + {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry{#1}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and +% such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{ +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\message{toc printing,} + +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{Table of Contents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{Short Contents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm Appendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in in \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +% +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +\let\ptexequiv = \equiv + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +\def\point{$\star$} + +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} + +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup +\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 +\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 +\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie +\catcode `\%=14 +\catcode 43=12 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces % +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \cartouche: draw rectangle w/rounded corners around argument +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +% This macro is +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller interline space and fonts for small examples. + \baselineskip 10pt + \indexfonts \tt + \rawbackslash % output the \ character from the current font + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking and narrows the margins. +% +\def\quotation{% +\begingroup\inENV %This group ends at the end of the @quotation body +{\parskip=0pt % because we will skip by \parskip too, later +\aboveenvbreak}% +\singlespace +\parindent=0pt +\let\Equotation = \nonfillfinish +% @cartouche defines \nonarrowing to inhibit narrowing +% at next level down. +\ifx\nonarrowing\relax +\advance \leftskip by \lispnarrowing +\advance \rightskip by \lispnarrowing +\exdentamount=\lispnarrowing +\let\nonarrowing=\relax +\fi} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % +\global\advance\parencount by 1 } +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. +% also in that case restore the outer-level definition of (. +\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi +\global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +\newif\ifinargs\inargsfalse +\def\keyword#1{% + \ifinargs{\df #1}\xdef\cumkeywords{\cumkeywords #1}% + \else\code{#1}\fi} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def\cumkeywords{}% +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\activeparens\spacesplit#3} + +\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def\cumkeywords{}% +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def\cumkeywords{}% +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +\def\defvrparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#4}}} + +% This seems to work right in all cases. +\let\deftpparsebody=\defvrparsebody +% This fails to work. When given `@deftp {Data Type} foo_t', +% it thinks the type name is just `f'. +%%% This is the same as all the others except for the last line. We need +%%% to parse the arguments differently for @deftp, since the ``attributes'' +%%% there are optional. +%%% +%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV % +%%\medbreak % +%%% Define the end token that this defining construct specifies +%%% so that it will exit this group. +%%\def#1{\endgraf\endgroup\medbreak}% +%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% +%%\parindent=0in +%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +%%\exdentamount=\defbodyindent +%%\begingroup\obeylines\parsetpheaderline{#3{#4}}} + +%%{\obeylines % +%% % Parse the type name and any attributes (field names, etc.). +%% % #1 is the beginning of the macro call that will produce the output, +%% % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody. +%% % #2 is the type name, e.g., `struct termios'. +%% % #3 is the (possibly empty) attribute list. +%% % +%% \gdef\parsetpheaderline#1#2#3^^M{% +%% \endgroup % Started in \deftpparsebody. +%% % +%% % If the attribute list is in fact empty, there will be no space after +%% % #2; so we can't put a space in our TeX parameter list. But if it +%% % isn't empty, then #3 will begin with an unwanted space. +%% \def\theargs{\ignorespaces #3}% +%% % +%% % Call the macro to produce the output. +%% #1{#2}\theargs % +%% }% +%%} + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0\inargstrue +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\functionparens\inargstrue +\code{#1}% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\doind {fn}{\code{#2\cumkeywords}}% +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{% +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\doind {fn}{\code{#1\cumkeywords}}% +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\begingroup\defname {\code{#1} #2}{Function}% +\deftypefunargs {#3}\endgroup % +\doind {fn}{\code{#2\cumkeywords}}% Make entry in function index +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\begingroup\defname {\code{#2} #3}{#1}% +\deftypefunargs {#4}\endgroup % +\doind {fn}{\code{#3\cumkeywords}}% Make entry in function index +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypemethod {Class} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypemethod{\defmethparsebody\Edeftypemethod\deftypemthx\deftypemthheader} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypemthheader #1#2#3{\deftypemthheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypemthheaderx #1#2#3 #4\relax{% +\begingroup\defname {\code{#2} #3}{Method on #1}% +\deftypefunargs {#4}\endgroup % +\dosubind {fn}{\code{#3\cumkeywords}}{on #1}% entry in function index +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{% +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\doind {fn}{\code{#1\cumkeywords}}% +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{% +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\doind {fn}{\code{#1\cumkeywords}}% +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop {Funny Method} foo-class frobnicate argument + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +\dosubind {fn}{\code{#2\cumkeywords}}{on #1}% Make entry in function index +} + +% @defmethod == @defop Method + +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} + +\def\defmethodheader #1#2#3{% +\begingroup\defname {#2}{Method on #1}% +\defunargs {#3}\endgroup % +\dosubind {fn}{\code{#2\cumkeywords}}{on #1}% entry in function index +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name. +\def\deftypevarheader #1#2{% +\doind {vr}{\code{#2}}% Make entry in variables index +\begingroup\defname {\code{#1} #2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% +\begingroup\defname {\code{#2} #3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + +\message{cross reference,} +% Define cross-reference macros +\newwrite \auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% \setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +%\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +%\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +%\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% For \xrefX, #1 is the node name, #2 the name of the Info +% cross-reference, #3 the printed node name, #4 the name of the Info +% file, #5 the name of the printed manual. All but the node name can be +% omitted. +% +\def\pxref#1{see \xrefX[#1,,,,,,,]} +\def\xref#1{See \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup% +\def\printedmanual{\ignorespaces #5}% +\def\printednodename{\ignorespaces #3}% +% +\setbox1=\hbox{\printedmanual}% +\setbox0=\hbox{\printednodename}% +\ifdim \wd0=0pt% +\def\printednodename{\ignorespaces #1}% +%%% Uncommment the following line to make the actual chapter or section title +%%% appear inside the square brackets. +%\def\printednodename{#1-title}% +\fi% +% +% +% If we use \unhbox0 and \unhbox1 to print the node names, TeX does +% not insert empty discretionaries after hyphens, which means that it +% will not find a line break at a hyphen in a node names. Since some +% manuals are best written with fairly long node names, containing +% hyphens, this is a loss. Therefore, we simply give the text of +% the node name again, so it is as if TeX is seeing it for the first +% time. +\ifdim \wd1>0pt +section ``\printednodename'' in \cite{\printedmanual}% +\else% +\turnoffactive% +\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}% +\fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \turnoffactive so that punctuation chars such as underscore +% work in node names. +\def\dosetq #1#2{{\let\folio=0 \turnoffactive% +\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% +\next}} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thischapter} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 Chapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + $\langle$un\-de\-fined$\rangle$% + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% Read the last existing aux file, if any. No error if none exists. + +% This is the macro invoked by entries in the aux file. +\def\xrdef #1#2{ +{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} + +\def\readauxfile{% +\begingroup +\catcode `\^^@=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\^^C=\other +\catcode `\^^D=\other +\catcode `\^^E=\other +\catcode `\^^F=\other +\catcode `\^^G=\other +\catcode `\^^H=\other +\catcode `\ =\other +\catcode `\^^L=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode 26=\other +\catcode `\^^[=\other +\catcode `\^^\=\other +\catcode `\^^]=\other +\catcode `\^^^=\other +\catcode `\^^_=\other +\catcode `\@=\other +\catcode `\^=\other +\catcode `\~=\other +\catcode `\[=\other +\catcode `\]=\other +\catcode`\"=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode `\$=\other +\catcode `\#=\other +\catcode `\&=\other +% `\+ does not work, so use 43. +\catcode 43=\other +% the aux file uses ' as the escape. +% Turn off \ as an escape so we do not lose on +% entries which were dumped with control sequences in their names. +% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ +% Reference to such entries still does not work the way one would wish, +% but at least they do not bomb out when the aux file is read in. +\catcode `\{=1 \catcode `\}=2 +\catcode `\%=\other +\catcode `\'=0 +\catcode `\\=\other +\openin 1 \jobname.aux +\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue +\global\warnedobstrue +\fi +% Open the new aux file. Tex will close it automatically at exit. +\openout \auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only.. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +\long\gdef\footnotezzz#1{\insert\footins{% + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + #1\strut}% +} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + + +% End of control word definitions. + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +%\hsize = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt + +\global\pagewidth=\hsize +\global\pageheight=\vsize + +\global\let\smalllisp=\smalllispx +\global\let\smallexample=\smalllispx +\global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt \char '042}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt \char '176}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +% \lvvmode is equivalent in function to \leavevmode. +% Using \leavevmode runs into trouble when written out to +% an index file due to the expansion of \leavevmode into ``\unhbox +% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our +% magic tricks with @. +\def\lvvmode{\vbox to 0pt{}} + +\catcode`\|=\active +\def|{{\tt \char '174}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +\def\turnoffactive{\let"=\normaldoublequote +\let~=\normaltilde +\let^=\normalcaret +\let_=\normalunderscore +\let|=\normalverticalbar +\let<=\normalless +\let>=\normalgreater +\let+=\normalplus} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi} + +%% These look ok in all fonts, so just make them not special. The @rm below +%% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/Documentation/todo.texi b/Documentation/todo.texi new file mode 100644 index 000000000..58388b2b2 --- /dev/null +++ b/Documentation/todo.texi @@ -0,0 +1,324 @@ +@ifset TODO_ONLY +@chapter GNU Objective-C Class Library To Do list, and Questions. +@c set the vars GOBJC_VERSION and GCC_VERSION +@include version.texi +@end ifset + +@section Projects Looking for Volunteers + +If you think you can do one of these projects, please let me know. Your +help is greatly appreciated! Send email to +@samp{mccallum@@gnu.ai.mit.edu}. + +@itemize + +@item Make the GNU Objective C runtime properly initialize the class +pointer of statically-created string objects (i.e. the string objects +created with the syntax @samp{@@"This is a constant string object"}). +See the relevant comments in gcc/objc-act.c. Once we get this working +I'll release the suite of String classes that I've already written. + +Please! Someone? I want to do this soon so that we can get the ensuing +interface changes done before too many people write code based on the +current deprecated char-pointer interfaces. + +@item Make the GNU Objective C runtime thread-safe. (Again, someone? +We really need this.) + +@item Write a test-suite for the library. Use dejagnu. + +@item Write a proper name server for SocketPort's. Currently we're just +hashing the name to a socket port number---we could get unwanted hash +collisions. This will also allow us to name a SocketPort after it's +been created. + +@item Make SocketPort more reliable than UDP. + +@item Add some features to the compiler: +@enumerate +@item You can't add __attribute__'s to methods. I want to use: +@smallexample + - (int) writeFormat: (const char *)format, ... + __attribute__ ((format (printf, 1, 2))); + - (int) readFormat: (const char *)format, ... + __attribute__ ((format (scanf, 1, 2))); +@end smallexample +@item I would like to be able to use a function name/pointer as an +argument to @@encode() and get a type string like the selector types. +@end enumerate + +@item Notification registration classes, notification classes. + +@item Write more/better random number generators. Make them conform to +the protocol . See RNGAdditiveCongruential. + +@item Write user-visible random number classes in the spirit of the +@samp{Random} class. Look at Smalltalk's ProbabilityDistribution +classes, and think about replacing the @samp{Random} class with +something more like these. How about Poisson and Gaussian distributions +also? + +@end itemize + + +@section My To Do's + +@itemize @bullet + +@item Many code fixes and cleanups, indicated with @samp{xxx} in the source. + +@item In remote object messaging, send exceptions back to the requestor. +I'm waiting for gcc 2.7 exceptions. + +@item Add Coding methods to all the other collection classes. + +@item Find method for detecting NeXT vs GNU runtime. Put it in +@samp{configure.in} and define @samp{NeXT_runtime}. + +@item +The LAMBDA macro doesn't work on all systems. Request a change to gcc +that make something like LAMBDA work on all systems. + +@item +Possibly change @code{-(int)compare:anObject} for Collection. How +should non-Indexed collections be ordered? + +@item +Think about restructuring the Collection heirarchy. We need an abstract +class for collections that are ordered, but whose order is fixed by the +-compare: method, i.e. not user-settable. We need non-mutable version +of the classes. The implementation of this stuff is crying out for +multiple inheritance or protocols-with-implementation! + +@item +Finish HashTable.m. Implement freeKeys:values: (What is this supposed +to do anyway?). Handle archiving of atom string, "%", keys. + +@item +Finish Time.m. Many methods are not yet implemented. + +@item +Write a good hash function for floats and doubles. +@c This from +@c libg++.texi: @code{unsigned int foldhash(double x);} a hash function for +@c doubles that exclusive-or's the first and second words of x, returning +@c the result as an integer. + +@item +Many implementations could be made more efficient. Libobjects hasn't +been efficiency tuned at all. Overridding more methods in certain +classes could make things more efficient (especially EltNodeCollector). +SplayTree's could be done using top-down splaying. collhash could be +completely reimplemented. ...and a lot more... + +@item +Fix bugs that arise when double's are included in the elt union. + +@item +Fix all the subclassResponsibility comments in objects/*.h + +@c @item +@c Look at __gcc_bcmp in libgcc2.c. + +@item +I will finish libobjects documentation. + +@end itemize + +@c ================================================================== +@section Questions + +I would greatly appreciate your feedback on the questions +below. Please email your thoughts to mccallum@@gnu.ai.mit.edu. + +@itemize @bullet + +@item +I want to put method names in texinfo indices, but the colons in the +method names are interfering with info's notion of menu item names and +node names. Help. Any ideas? (Kresten?) + +@item +I need to read through al the enumState code again and clean it up. +Perhaps we'd like an Iterator class to use as a wrapper around the +enumState functionality? The NIH Class Library organizes things this +way. + +@item +Should we keep the -safe... enumeration methods? They sure do add a +lot of clutter to the protocols. If we got rid of them people would +have to alloc an Array, copy the contents, and free the Array +themselves. + +@item +What would people think about removing the ...Object methods, and just +having the ...Element methods instead? It might be a bit more difficult +to use, but it would reduce clutter significantly. The ...Element +methods are more efficient to use anyway, since most ...Object methods +are wrappers around ...Element calls. I'm not sure what I think we +should do. + +Here's an idea: Define the ...Object methods as macros. But we need a +new macro scheme that works for methods instead of functions. We would +need something with the following functionality: +@smallexample +#define [REC replaceObject: OLDOBJ with: NEWOBJ] \ + ([REC replaceElement:(elt)(OLDOBJ) with:(elt)(NEWOBJ)].id_u) +@end smallexample +The issue of macros for methods has been mentioned in email +found in the gnu-objc-issues archive, in the file @samp{preprocessor}. + +@item +It would be nice to have more error checking on the types going in and +out of a collection. When some code tries to put a float into a +collector initialized to hold integers, it would be nice to catch that. +Perhaps just some macros that will do the appropriate checks? It would +also be nice if elt's returned from methods were automatically casted to +the correct type. + +It might be good to use something like this (from the gcc +PROJECTS file): +@example +* A way of defining a structure containing a union, in which the choice +of union alternative is controlled by a previous structure component. + +Here is a possible syntax for this. + +struct foo @{ + enum @{ INT, DOUBLE @} code; + auto union @{ case INT: int i; case DOUBLE: double d;@} value : code; +@}; +@end example + +This has the disadvantage that now elt's will take up more than one +word. + +What I would prefer is something more radical: Some efficient way to +enable int's, float's to receive Objective-C messages. Then I wouldn't +have to worry about any of these horrible elt typing issues; I wouldn't +have to worry about all the ...Object ...Element method name +duplication; I wouldn't have to worry about the inefficiency of having +all the ...Object methods just be covers for the ...Element methods. +Lots of other Objective-C code would find this useful too. It has +the advantage of fixing the previous question also (about removing the +...Element ...Object method duplication). We need Objective-C objects +that can live on the stack. + +For now, I've worked out a ObjC++ solution to this with constructors and +casting operators. Now I'm just waiting for Kresten to finish ObjC++. + +@item +Perhaps we should put more safety checks into LinkedList, +BinaryTree, etc: Check that node is not already part of another +collection (by checking that neighbor pointers are nil?) In method +"insertObject:newObject after:oldObject" make sure that oldObject is a +member of self. ...It seems that there is a lot of potential for +nasty bugs with mistakes like these. + +@item +HashTable.m (-initKeyDesc:valueDesc:capacity:) I tried to make it +portable, but I didn't try very hard. Anyone want to send in fixes? + +@item +I fixed -emptyCopy in all the subclasses, but the -emptyCopy scheme +seems pretty fragile. How about calling -initFoo: inside -emptyCopy? +This way we avoid having yet another method in which instance vars +must be initialized to some consistent state. -allocCopy would never +even get called. <> + +@item +The situation with LinkedListNode and LinkedListEltNode, (and the +analagous classes for BinaryTree's and RBTree's) are just crying out +for multiple inheritance. Anyone have ideas that are prettier than my +quick fix using #include ? Anyone have an alternate organization that +doesn't need multiple inheritance? + +@item +Somes classes, like RBTree, depend on a certain ordering of elements +to maintain internal consistency. How should we define the behavior +of methods whose names imply that the user can set the ordering of +elements independent of these constraints? (like -appendElement: or +-insertElement:atIndex: for instance). I see three possibilities: +@enumerate + @item The methods do what they say. Give the user the power to +override the default ordering. + @item The methods do not do what they say, but call addElement: +instead. This lets the class maintain its internal consistency, but +it has the potential to be a bit confusing to the user. What would +happen if the user sent a sort message to such a class, for instance? + @item The methods trigger a -shouldNotImplement: error. This solution +perhaps best expresses the reality of the situation, but it's a bit +strange for a class to signal an error on a method which is in a +protocol the class conforms to. +@end enumerate + Currently I'm using solution #1 (in most classes?). + +@item +I created libobjects.texi by copying libg++.texi. Some of the text +is taken verbatim. Is this a problem? + +@item +If you don't like the organization of the documentation and you have +suggestions for changes, please say so now, not after it's all been +written. + +@item +Does anyone really miss the ability to set the comparison function +independent of the element encoding? If it's really important we can +come up with ways to do this and still be able to archive comparison +functions. + +@item +Something like this needed? +- elementDidChange: (elt*)elementPtr; +Currently you have to remove, change, add, for some classes. + +@c ------------------------------------------------------------------- +@c @section Questions leftover from last release + +@item +Opinions on the error reporting scheme? See also +@samp{checks/test05.m}. This error reporting scheme will most likely +change completely as soon as gcc gets exception handling. + +@item +Should I include _comparison_function as an instance variable of +Collection? Putting it back in could make some things more efficient, +but several classes don't have configurable comparisonFunction's +(i.e. String, LinkedList, BinaryTree, RBTree), so they don't need it. + +@item +I've been told that GNU filenames should be 14 chars or less. I +don't want to abbreviate my classnames, but I think using .h +@@interface files with names different than the class name is even +worse. ** I want to keep my unabbreviated filenames!! ** What to do, +what to do... I can't believe that *all* GNU classnames will be +limited to 12 characters forever and ever---disgusting. + +@end itemize + +@c ================================================================== +@section Changes I'd like in the Objective-C runtime and gcc: + +@itemize @bullet + +@item +Make OBJC_MALLOC() and friends public. Have the runtime and +Object.m use them. See objc-malloc.[hm]. + +@item +Give hash.[hc] functionality more like collhash.[hc], i.e.: +Add hash_node_for_key() to hash.h and hash.c. +Change hash_next() so that more than one enumeration of the contents +can happen concurrently. +How about removing cache as a parameter to the hashing functions in +hash.h and hash.c. Do the masking on the result of the hash function. +This seems much neater to me. + +@item +Add a way of defining a structure containing a union, in which the choice +of union alternative is controlled by a previous structure component. +(See gcc @samp{PROJECTS} file.) + +@end itemize diff --git a/Examples/Makefile.in b/Examples/Makefile.in new file mode 100644 index 000000000..5c5a05f55 --- /dev/null +++ b/Examples/Makefile.in @@ -0,0 +1,129 @@ +# +# Examples makefile for Objective-C Class Library +# Copyright (C) 1993 Free Software Foundation, Inc. +# +# Written by: R. Andrew McCallum +# Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 +# +# This file is part of the GNU Objective-C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +SHELL = /bin/sh + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ + +CFLAGS = -Wall -Wno-implicit -g -O +CPPFLAGS = +LDFLAGS = + +DEFS = @DEFS@ +LIBS = -L$(srcdir)/.. -lobjects @LIBOBJC@ @LIBS@ + +#### End of system configuration section. #### + +NEXT_NEXT_INCLUDES = -I/usr/include +OBJECTS_NEXT_INCLUDES = -I$(srcdir)/../objects/next-include +NEXT_INCLUDES = @NEXT_INCLUDES@ + +ALL_CPPFLAGS = -I$(srcdir)/.. $(NEXT_INCLUDES) $(CPPFLAGS) +ALL_CFLAGS = $(CFLAGS) +ALL_OBJCFLAGS = $(CFLAGS) -Wno-protocol +ALL_LDFLAGS = $(LDFLAGS) $(LIBS) + +.SUFFIXES: .m +.m.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) $< -o $*.o +.c.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_CFLAGS) $< -o $*.o + +SRCS = \ +dictionary.m \ +stdio-stream.m \ +textcoding.m \ +port-server.m \ +port-client.m \ +first-server.m \ +first-client.m \ +second-server.m \ +second-client.m + +HDRS = \ +first-server.h \ +second-server.h \ +second-client.h + +EXCS = $(SRCS:.m=) + +all: $(EXCS) + +# This works for GNU make, but not others. +# %: %.o $(srcdir)/../libobjects.a +# $(CC) $(ALL_CFLAGS) $< -o $@ $(ALL_LDFLAGS) +# How can I do this in a better way than the ugliness below? +# (but also have it work on old-style /bin/make) + +LINK_CMD = $(CC) $(ALL_CFLAGS) $@.o -o $@ $(ALL_LDFLAGS) +dictionary: dictionary.o $(srcdir)/../libobjects.a + $(LINK_CMD) +stdio-stream: stdio-stream.o $(srcdir)/../libobjects.a + $(LINK_CMD) +textcoding: textcoding.o $(srcdir)/../libobjects.a + $(LINK_CMD) +port-server: port-server.o $(srcdir)/../libobjects.a + $(LINK_CMD) +port-client: port-client.o $(srcdir)/../libobjects.a + $(LINK_CMD) +first-server: first-server.o $(srcdir)/../libobjects.a + $(LINK_CMD) +first-client: first-client.o $(srcdir)/../libobjects.a + $(LINK_CMD) +second-server: second-server.o $(srcdir)/../libobjects.a + $(LINK_CMD) +second-client: second-client.o $(srcdir)/../libobjects.a + $(LINK_CMD) + +first: first-server first-client +second: second-server second-client +port: port-server port-client + +DISTFILES = $(SRCS) $(HDRS) Makefile.in + +mostlyclean: + rm -f core *~ + +clean: mostlyclean + rm -f *.o $(EXCS) + +distclean: clean + rm -f Makefile config.status + +realclean: distclean + rm -f TAGS + +dist-dir: $(srcdir)/../.fname + @echo Run make dist from the parent directory. + +dist: $(DISTFILES) dist-dir + mkdir $(srcdir)/../`cat $(srcdir)/../.fname`/examples + ln $(DISTFILES) $(srcdir)/../`cat $(srcdir)/../.fname`/examples + +Makefile: Makefile.in + cd $(srcdir)/..; $(SHELL) config.status diff --git a/Examples/dictionary.m b/Examples/dictionary.m new file mode 100644 index 000000000..9e53dcac1 --- /dev/null +++ b/Examples/dictionary.m @@ -0,0 +1,40 @@ +/* A simple demonstration of the GNU Dictionary object. + In this example the Dictionary holds int's which are keyed by strings. */ + +#include +#include + +int main() +{ + id d; + + /* Create a Dictionary object that will store int's with string keys */ + d = [[Dictionary alloc] + initWithType:@encode(int) + keyType:@encode(char*)]; + + /* Load the dictionary with some items */ + [d putElement:1 atKey:"one"]; + [d putElement:2 atKey:"two"]; + [d putElement:3 atKey:"three"]; + [d putElement:4 atKey:"four"]; + [d putElement:5 atKey:"five"]; + [d putElement:6 atKey:"six"]; + + printf("There are %u elements stored in the dictionary\n", + [d count]); + + printf("Element %d is stored at \"%s\"\n", + [d elementAtKey:"three"].int_u, "three"); + + printf("Removing element stored at \"three\"\n"); + [d removeElementAtKey:"three"]; + + printf("Removing element 2\n"); + [d removeElement:2]; + + printf("Now there are %u elements stored in the dictionary\n", + [d count]); + + exit(0); +} diff --git a/Examples/first-client.m b/Examples/first-client.m new file mode 100644 index 000000000..cb479a6ca --- /dev/null +++ b/Examples/first-client.m @@ -0,0 +1,34 @@ + +#include +#include "first-server.h" + +int main(int argc, char *argv[]) +{ + id s; + + if (argc > 2) + { + printf("Looking for connection named `firstserver' on host `%s'...\n", + argv[2]); + s = [Connection rootProxyAtName:"firstserver" onHost:argv[2]]; + } + else + { + printf("Looking for connection named `firstserver' on localhost...\n"); + s = [Connection rootProxyAtName:"firstserver"]; + } + + printf("Found connection named `firstserver'\n"); + + printf("Saying hello to the server\n"); + if (argc > 1) + [s sayHiTo:argv[1]]; + else + [s sayHiTo:"out there"]; + + + printf("Shutting down my connection to the server\n"); + [s free]; + + exit(0); +} diff --git a/Examples/first-server.h b/Examples/first-server.h new file mode 100644 index 000000000..432a2489d --- /dev/null +++ b/Examples/first-server.h @@ -0,0 +1,13 @@ + +#ifndef _first_server_h +#define _first_server_h + +#include + +@interface FirstServer : Object + +- sayHiTo: (char *)name; + +@end + +#endif /* _first_server_h */ diff --git a/Examples/first-server.m b/Examples/first-server.m new file mode 100644 index 000000000..348e58d7c --- /dev/null +++ b/Examples/first-server.m @@ -0,0 +1,30 @@ + +#include +#include "first-server.h" + +@implementation FirstServer +- sayHiTo: (char *)name +{ + printf("Hello, %s.\n", name); + return self; +} +@end + +int main() +{ + id s, c; + + /* Create our server object */ + s = [[FirstServer alloc] init]; + + /* Register a connection that provides the server object to the network */ + printf("Registering a connection for the server using name `firstserver'\n"); + c = [Connection newRegisteringAtName:"firstserver" + withRootObject:s]; + + /* Run the connection */ + printf("Running the connection... (until you interrupt with control-C)\n"); + [c runConnection]; /* This runs until interrupt. */ + + exit(0); +} diff --git a/Examples/port-client.m b/Examples/port-client.m new file mode 100644 index 000000000..9110e1ffc --- /dev/null +++ b/Examples/port-client.m @@ -0,0 +1,39 @@ +#include +#include + +#define MSG "Hello from a client SocketPort." +#define BUFFER_SIZE 80 + +int main(int argc, char *argv[]) +{ + char b[BUFFER_SIZE]; + int len; + id remotePort; + id localPort = [SocketPort newLocal]; + id rp; + + if (argc > 1) + remotePort = [SocketPort newRemoteWithNumber:3 onHost:argv[1]]; + else + remotePort = [SocketPort newRemoteWithNumber:3 onHost:""]; + + strcpy(b, MSG); + [localPort sendPacket:b length:strlen(b) + toPort:remotePort + timeout: 15000]; + len = [localPort receivePacket:b length:BUFFER_SIZE + fromPort:&rp + timeout:15000]; + + if (len == -1) + { + fprintf(stderr, "receive from SocketPort timed out\n"); + } + else + { + b[len] = '\0'; + printf("(length %d): %s\n", len, b); + } + + exit(0); +} diff --git a/Examples/port-server.m b/Examples/port-server.m new file mode 100644 index 000000000..d8f182d91 --- /dev/null +++ b/Examples/port-server.m @@ -0,0 +1,28 @@ +#include +#include + +#define MSG "Hello back to you, from a server SocketPort" +#define BUFFER_SIZE 80 + +int main() +{ + char b[BUFFER_SIZE]; + int l; + id p = [SocketPort newLocalWithNumber:3]; + id rp; + + for (;;) + { + l = [p receivePacket:b length:BUFFER_SIZE + fromPort:&rp + timeout:-1]; + if (l >= 0 && l < 32) + b[l] = '\0'; + printf("(length %d): %s\n", l, b); + + [p sendPacket:MSG length:strlen(MSG) + toPort:rp + timeout:15000]; + } + exit(0); +} diff --git a/Examples/second-client.h b/Examples/second-client.h new file mode 100644 index 000000000..ae91a1e3f --- /dev/null +++ b/Examples/second-client.h @@ -0,0 +1,30 @@ +#ifndef second_client_h +#define second_client_h + +#include +#include +#include "second-server.h" + +@interface AppellationObject : Object +{ + const char *appellation; +} + +@end + +@implementation AppellationObject + +- setAppellation: (const char *)n +{ + appellation = n; + return self; +} + +- (const char *) appellation +{ + return appellation; +} + +@end + +#endif diff --git a/Examples/second-client.m b/Examples/second-client.m new file mode 100644 index 000000000..3888450eb --- /dev/null +++ b/Examples/second-client.m @@ -0,0 +1,47 @@ +#include "second-client.h" + +int main(int argc, char *argv[]) +{ + id server; + id a1; + id remote_array; + char namebuf[16]; + + printf("Looking up server object on localhost with name `secondserver'\n"); + server = [Connection rootProxyAtName:"secondserver"]; + printf("Found server.\n"); + + /* Create an AppellationObject */ + a1 = [[AppellationObject alloc] init]; + sprintf(namebuf, "%d", getpid()); + [a1 setAppellation:namebuf]; + printf("This client has appellation %s\n", [a1 appellation]); + + /* Let the server know about object a1. */ + [server addRemoteObject:a1]; + + /* Get the server's array of all other AppellationObject's */ + remote_array = [server array]; + + /* Print all the appellations */ + { + int i, count; + const char *s; + + count = [remote_array count]; + for (i = 0; i < count; i++) + { + s = [[remote_array objectAtIndex:i] appellation]; + printf("Server knows about client with appellation %s\n", s); + (*objc_free)((void*)s); + } + } + + /* Run, exiting as soon as there are 15 seconds with no requests */ + [[server connectionForProxy] runConnectionWithTimeout:15000]; + + /* Clean up, to let the server know we're going away */ + [[server connectionForProxy] free]; + + exit(0); +} diff --git a/Examples/second-server.h b/Examples/second-server.h new file mode 100644 index 000000000..6a77ad0f5 --- /dev/null +++ b/Examples/second-server.h @@ -0,0 +1,19 @@ +#ifndef second_server_h +#define second_server_h + +#include +#include +#include + +@interface SecondServer : Object +{ + Array *array; +} + +- init; +- addRemoteObject: o; +- array; + +@end + +#endif diff --git a/Examples/second-server.m b/Examples/second-server.m new file mode 100644 index 000000000..b11e53979 --- /dev/null +++ b/Examples/second-server.m @@ -0,0 +1,89 @@ +#include "second-server.h" +#include "second-client.h" +#include + +@implementation SecondServer + +- init +{ + [super init]; + array = [[Array alloc] init]; + return self; +} + +- addRemoteObject: o +{ + const char *s; + [array addObject:o]; + + /* This next line is a callback */ + s = [o appellation]; + printf("Added remote object with appellation %s\n", s); + + /* Free it because the remote messaging system malloc'ed it for us, + and we don't need it anymore. */ + (*objc_free)((void*)s); + return self; +} + +- array +{ + return array; +} + +- (Connection*) connection: ancestor didConnect: newConn +{ + printf("New connection created\n"); + [newConn registerForInvalidationNotification:self]; + [newConn setDelegate:self]; + return newConn; +} + +- senderIsInvalid: sender +{ + if ([sender isKindOf:[Connection class]]) + { + id remotes = [sender proxies]; + int remotesCount = [remotes count]; + int arrayCount = [array count]; + int i, j; + + printf("Connection invalidated\n"); + + /* This contortion avoids Array's calling -isEqual: on the proxy */ + for (j = 0; j < remotesCount; j++) + for (i = 0; i < arrayCount; i++) + if ([remotes objectAtIndex:j] == [array objectAtIndex:i]) + { + printf("removing remote proxy from the list\n"); + [array removeObjectAtIndex:j]; + break; + } + [remotes free]; + } + else + { + [self error:"non-Connection sent invalidation"]; + } + return self; +} + +@end + +int main(int argc, char *argv[]) +{ + id s; + id c; + + s = [[SecondServer alloc] init]; + + c = [Connection newRegisteringAtName:"secondserver" withRootObject:s]; + printf("Regsitered server object on localhost with name `secondserver'\n"); + + [c setDelegate:s]; + [c registerForInvalidationNotification:s]; + + [c runConnection]; + + exit(0); +} diff --git a/Examples/stdio-stream.m b/Examples/stdio-stream.m new file mode 100644 index 000000000..6c37d3b01 --- /dev/null +++ b/Examples/stdio-stream.m @@ -0,0 +1,37 @@ +/* A simple example of writing and reading to a file using the + GNU StdioStream object. */ + +#include + +int main() +{ + id stream; + int count = 0; + int i = 0; + float f = 0.0; + double d = 0.0; + unsigned u = 0; + unsigned char uc = 0; + unsigned ux = 0; + char *cp = NULL; + + stream = [[StdioStream alloc] + initWithFilename:"./stdio-stream.txt" + fmode:"w"]; + [stream writeFormat:"testing %d %u %f %f 0x%x \"cow\"\n", + 1234, 55, 3.14159, 1.23456789, 0xfeedface]; + [stream free]; + + stream = [[StdioStream alloc] + initWithFilename:"./stdio-stream.txt" + fmode:"r"]; + count = [stream readFormat:"testing %d %u %f %lf 0x%x \"%a[^\"]\"\n", + &i, &u, &f, &d, &ux, &cp]; + uc = (unsigned char) ux; + [stream free]; + printf("Read count=%d, int=%d unsigned=%u float=%f double=%f " + "uchar=0x%x char*=%s\n", + count, i, u, f, d, (unsigned)uc, cp); + + exit(0); +} diff --git a/Examples/textcoding.m b/Examples/textcoding.m new file mode 100644 index 000000000..862152528 --- /dev/null +++ b/Examples/textcoding.m @@ -0,0 +1,100 @@ +/* A demonstration of writing and reading GNU Objective C objects to a file, + in human-readable text format. + Look at the file "textcoding.txt" after running this program to see the + text archive format. + */ + +#include +#include +#include +#include +#include +#include + +int main() +{ + id set, ll; + id stream; + id coder; + const char *n; + + /* Create a Set of int's + and a LinkedList of float's */ + set = [[Set alloc] initWithType:@encode(int)]; + ll = [[EltNodeCollector alloc] initWithType:@encode(float) + nodeCollector:[[LinkedList alloc] init] + nodeClass:[LinkedListEltNode class]]; + + /* Populate the Set and display it */ + [set addElement:1234567]; + [set addElement:2345678]; + [set addElement:3456789]; + [set addElement:4567891]; + [set addElement:5678912]; + [set printForDebugger]; + + /* Populate the LinkedList and display it */ + [ll addElement:1.2f]; + [ll addElement:(float)3.4]; + [ll addElement:(float)5.6]; + [ll addElement:(float)7.8]; + [ll addElement:(float)9.0]; + [ll printForDebugger]; + + /* Write them to a file */ + stream = [[StdioStream alloc] + initWithFilename:"./textcoding.txt" + fmode:"w"]; + coder = [[TextCoder alloc] initEncodingOnStream:stream]; + [coder encodeObject:set withName:"Test Set"]; + [coder encodeObject:ll withName:"Test EltNodeCollector LinkedList"]; + + /* Free the objects */ + [coder free]; + [set free]; + [ll free]; + + /* Read them back in from the file */ + /* First init the stream and coder */ + stream = [[StdioStream alloc] + initWithFilename:"./textcoding.txt" + fmode:"r"]; + coder = [[TextCoder alloc] initDecodingOnStream:stream]; + + /* Read in the Set */ + [coder decodeObjectAt:&set withName:&n]; + printf("got object named %s\n", n); + /* The name was malloc'ed by the Stream, free it */ + (*objc_free)((void*)n); + + /* Read in the LinkedList */ + [coder decodeObjectAt:&ll withName:&n]; + printf("got object named %s\n", n); + /* The name was malloc'ed by the Stream, free it */ + (*objc_free)((void*)n); + + /* Display what we read, to make sure it matches what we wrote */ + [set printForDebugger]; + [ll printForDebugger]; + + /* Free the objects */ + [coder free]; + [set free]; + [ll free]; + + exit(0); +} + +/* Some notes: + + This program is a great example of how allocating and freeing + memory is very screwed up: + + * The Stream allocates the name, we have to free it. + + * The Coder free's its Stream when the Coder is free'd, but we + were the ones to create it. + + These difficult and ad-hoc rules will be fixed in the future. + +*/ diff --git a/Headers/gnustep/base/Array.h b/Headers/gnustep/base/Array.h new file mode 100644 index 000000000..6f49482d0 --- /dev/null +++ b/Headers/gnustep/base/Array.h @@ -0,0 +1,65 @@ +/* Interface for Objective-C Array collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Array_h_INCLUDE_GNU +#define __Array_h_INCLUDE_GNU + +#include +#include + +@interface Array : IndexedCollection +{ + @public + int (*_comparison_function)(elt,elt); + elt *_contents_array; + unsigned int _count; + unsigned int _capacity; + unsigned int _grow_factor; +} + ++ (unsigned) defaultCapacity; ++ (unsigned) defaultGrowFactor; + +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; +- initWithCapacity: (unsigned) aCapacity; + +- setCapacity: (unsigned)newCapacity; +- (unsigned) growFactor; +- setGrowFactor: (unsigned)aNum; + +@end + +#define FOR_ARRAY(ARRAY, ELEMENT_VAR) \ +{ \ + unsigned _FOR_ARRAY_i; \ + for (_FOR_ARRAY_i = 0; \ + _FOR_ARRAY_i < ((Array*)ARRAY)->_count; \ + _FOR_ARRAY_i++) \ + { \ + ELEMENT_VAR = \ + (((Array*)ARRAY)->_contents_array[_FOR_ARRAY_i]); + +#define FOR_ARRAY_END }} + +#endif /* __Array_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/ArrayPrivate.h b/Headers/gnustep/base/ArrayPrivate.h new file mode 100644 index 000000000..a691a0772 --- /dev/null +++ b/Headers/gnustep/base/ArrayPrivate.h @@ -0,0 +1,87 @@ +/* Array definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ArrayPrivate_h_INCLUDE_GNU +#define __ArrayPrivate_h_INCLUDE_GNU + +#include +#include + +#define DEFAULT_ARRAY_CAPACITY 2 +#define DEFAULT_ARRAY_GROW_FACTOR 2 + + +/* Routines that help with inserting and removing elements */ + +/* Assumes that _count has already been incremented to make room + for the hole. The data at _contents_array[_count-1] is not part + of the collection). */ +static inline void +makeHoleAt(Array *self, unsigned index) +{ + int i; + + for (i = (self->_count)-1; i > index; i--) + self->_contents_array[i] = self->_contents_array[i-1]; +} + +/* Assumes that _count has not yet been decremented. The data at + _contents_array[_count-1] is part of the collection. */ +static inline void +fillHoleAt(Array *self, unsigned index) +{ + int i; + + for (i = index; i < (self->_count)-1; i++) + self->_contents_array[i] = self->_contents_array[i+1]; +} + +/* These are the only two routines that change the value of the instance + variable _count, except for "-initWithType:capacity:" and "-empty" */ + +/* Should these be methods instead of functions? Doing so would make + them slower. */ + +/* Do this before adding an element */ +static inline void +incrementCount(Array *self) +{ + (self->_count)++; + if (self->_count == self->_capacity) + { + [self setCapacity:(self->_capacity) * self->_grow_factor]; + } +} + +/* Do this after removing an element */ +static inline void +decrementCount(Array *self) +{ + (self->_count)--; + if (self->_count < (self->_capacity) / self->_grow_factor) + { + [self setCapacity:(self->_capacity) / self->_grow_factor]; + } +} + +#endif /* __ArrayPrivate_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Bag.h b/Headers/gnustep/base/Bag.h new file mode 100644 index 000000000..4e6a6e679 --- /dev/null +++ b/Headers/gnustep/base/Bag.h @@ -0,0 +1,63 @@ +/* Interface for Objective-C Bag collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Bag_h_INCLUDE_GNU +#define __Bag_h_INCLUDE_GNU + +#include +#include + +@interface Bag : Set +{ + unsigned int _count; // the number of elements; +} + +// ADDING; +- addObject: newObject withOccurrences: (unsigned)count; + +// REMOVING AND REPLACING; +- removeObject: oldObject occurrences: (unsigned)count; +- removeObject: oldObject occurrences: (unsigned)count + ifAbsentCall: (id(*)(arglist_t))excFunc; + +// TESTING; +- (unsigned) uniqueCount; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING AND FREEING; +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; + +// ADDING; +- addElement: (elt)newElement withOccurrences: (unsigned)count; + +// REMOVING AND REPLACING; +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count; +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +@end + +#endif /* __Bag_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/BinaryTree.h b/Headers/gnustep/base/BinaryTree.h new file mode 100644 index 000000000..ef35e54cd --- /dev/null +++ b/Headers/gnustep/base/BinaryTree.h @@ -0,0 +1,75 @@ +/* Interface for Objective-C BinaryTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Binary Tree. + Base class for smarter binary trees. +*/ + +#ifndef __BinaryTree_h_INCLUDE_GNU +#define __BinaryTree_h_INCLUDE_GNU + +#include +#include + +/* The protocol defines the interface to an object + that may be an element in a BinaryTree. +*/ +@protocol BinaryTreeComprising +- leftNode; +- rightNode; +- parentNode; +- setLeftNode: (id )aNode; +- setRightNode: (id )aNode; +- setParentNode: (id )aNode; +@end + +#define NODE_IS_RIGHTCHILD(NODE) (NODE == [[NODE parentNode] rightNode]) +#define NODE_IS_LEFTCHILD(NODE) (NODE == [[NODE parentNode] leftNode]) + +@interface BinaryTree : IndexedCollection +{ + unsigned int _count; + id _contents_root; +} + +- nilNode; +- rootNode; + +- leftmostNodeFromNode: aNode; +- rightmostNodeFromNode: aNode; + +- (unsigned) depthOfNode: aNode; +- (unsigned) heightOfNode: aNode; + +- (unsigned) nodeCountUnderNode: aNode; + +- leftRotateAroundNode: aNode; +- rightRotateAroundNode: aNode; + +- binaryTreePrintForDebugger; + +@end + + +#endif /* __BinaryTree_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/BinaryTreeEltNode.h b/Headers/gnustep/base/BinaryTreeEltNode.h new file mode 100644 index 000000000..b7912a1e5 --- /dev/null +++ b/Headers/gnustep/base/BinaryTreeEltNode.h @@ -0,0 +1,36 @@ +/* Interface for Objective-C BinaryTreeEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __BinaryTreeEltNode_h_INCLUDE_GNU +#define __BinaryTreeEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface BinaryTreeEltNode : BinaryTreeNode +#include +@end + + +#endif /* __BinaryTreeEltNode_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/BinaryTreeNode.h b/Headers/gnustep/base/BinaryTreeNode.h new file mode 100644 index 000000000..2a3d255c8 --- /dev/null +++ b/Headers/gnustep/base/BinaryTreeNode.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C BinaryTreeNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __BinaryTreeNode_h_INCLUDE_GNU +#define __BinaryTreeNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface BinaryTreeNode : Object +{ + id _left; + id _right; + id _parent; +} +@end + + +#endif /* __BinaryTreeNode_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/CircularArray.h b/Headers/gnustep/base/CircularArray.h new file mode 100644 index 000000000..b4b138b84 --- /dev/null +++ b/Headers/gnustep/base/CircularArray.h @@ -0,0 +1,38 @@ +/* Interface for Objective-C CircularArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CircularArray_h_INCLUDE_GNU +#define __CircularArray_h_INCLUDE_GNU + +#include +#include + +@interface CircularArray : Array +{ + @public + unsigned int _start_index; +} + +@end + +#endif /* __CircularArray_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/CircularArrayPrivate.h b/Headers/gnustep/base/CircularArrayPrivate.h new file mode 100644 index 000000000..67f0e5580 --- /dev/null +++ b/Headers/gnustep/base/CircularArrayPrivate.h @@ -0,0 +1,75 @@ +/* CircularArray definitions for the use of subclass implementations + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CircularArrayPrivate_h_INCLUDE_GNU +#define __CircularArrayPrivate_h_INCLUDE_GNU + +#include +#include + +#define CIRCULAR_TO_BASIC(INDEX) \ + ((INDEX + self->_start_index) % self->_capacity) + +#define BASIC_TO_CIRCULAR(INDEX) \ + ((INDEX + self->_capacity - self->_start_index) % self->_capacity) + +#define NEXT_CIRCULAR_INDEX(INDEX) \ + ((INDEX + 1) % self->_capacity) + +#define PREV_CIRCULAR_INDEX(INDEX) \ + ((INDEX + self->_capacity - 1) % self->_capacity) + +static inline void +circularMakeHoleAt(CircularArray *self, unsigned basicIndex) +{ + int i; + if (self->_start_index && basicIndex > self->_start_index) + { + for (i = self->_start_index; i < basicIndex; i++) + self->_contents_array[i-1] = self->_contents_array[i]; + } + else + { + for (i = CIRCULAR_TO_BASIC(self->_count-1); i >= basicIndex; i--) + self->_contents_array[i+1] = self->_contents_array[i]; + } + /* This is never called with _count == 0 */ +} + +static inline void +circularFillHoleAt(CircularArray *self, unsigned basicIndex) +{ + int i; + if (basicIndex > self->_start_index) + { + for (i = basicIndex; i > self->_start_index; i--) + self->_contents_array[i] = self->_contents_array[i-1]; + } + else + { + for (i = basicIndex; i < CIRCULAR_TO_BASIC(self->_count-1); i++) + self->_contents_array[i] = self->_contents_array[i+1]; + } +} + +#endif /* __CircularArrayPrivate_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Coder.h b/Headers/gnustep/base/Coder.h new file mode 100644 index 000000000..1005810e9 --- /dev/null +++ b/Headers/gnustep/base/Coder.h @@ -0,0 +1,158 @@ +/* Interface for GNU Objective-C coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Coder_h +#define __Coder_h + +#include +#include + +@class Stream; +@class Dictionary; +@class Stack; + +@interface Coder : Object +{ + int format_version; + int concrete_format_version; + Stream *stream; + BOOL is_decoding; + BOOL doing_root_object; + Dictionary *object_table; /* read/written objects */ + Dictionary *const_ptr_table; /* read/written const *'s */ + Stack *root_object_tables; /* Stack of Dicts for interconnt'd objs */ + Stack *forward_object_tables; /* Stack of Dictionaries for frwd refs */ +} + ++ (void) setDefaultStreamClass: sc; ++ defaultStreamClass; ++ setDebugging: (BOOL)f; + +- initEncodingOnStream: (Stream *)s; +- initDecodingOnStream: (Stream *)s; +- initEncoding; +- initDecoding; +- init; + +- free; +- (BOOL) isDecoding; + +- (void) encodeValueOfType: (const char*)type + at: (const void*)d + withName: (const char *)name; +- (void) decodeValueOfType: (const char*)type + at: (void*)d + withName: (const char **)namePtr; + +- (void) encodeWithName: (const char *)name + valuesOfTypes: (const char *)types, ...; +- (void) decodeWithName: (const char **)name + valuesOfTypes: (const char *)types, ...; + +- (void) encodeArrayOfType: (const char *)type + at: (const void *)d + count: (unsigned)c + withName: (const char *)name; +- (void) decodeArrayOfType: (const char *)type + at: (void *)d + count: (unsigned *)c + withName: (const char **)name; + +- (void) encodeObject: anObj + withName: (const char *)name; +- (void) encodeObjectBycopy: anObj + withName: (const char *)name; +- (void) decodeObjectAt: (id*)anObjPtr + withName: (const char **)name; + +- (void) encodeRootObject: anObj + withName: (const char *)name; +- (void) encodeObjectReference: anObj + withName: (const char *)name; +- (void) startEncodingInterconnectedObjects; +- (void) finishEncodingInterconnectedObjects; +- (void) startDecodingInterconnectedObjects; +- (void) finishDecodingInterconnectedObjects; + +- (void) encodeAtomicString: (const char*)sp + withName: (const char*)name; +- (const char *) decodeAtomicStringWithName: (const char **)name; + +- decodeClass; +- (void) encodeClass: aClass; + +/* For inserting a name into a TextCoder stream */ +- (void) encodeName: (const char*)n; +- (void) decodeName: (const char**)n; + +/* For subclasses that want to keep track of recursion */ +- (void) encodeIndent; +- (void) encodeUnindent; +- (void) decodeIndent; +- (void) decodeUnindent; + +/* Implemented by concrete subclasses */ +- (void) encodeValueOfSimpleType: (const char*)type + at: (const void*)d + withName: (const char *)name; +- (void) decodeValueOfSimpleType: (const char*)type + at: (void*)d + withName: (const char **)namePtr; +- (void) encodeBytes: (const char *)b + count: (unsigned)c + withName: (const char *)name; +- (void) decodeBytes: (char *)b + count: (unsigned*)c + withName: (const char **)name; + +- (int) coderFormatVersion; +- (int) coderConcreteFormatVersion; + +- (void) resetCoder; /* xxx remove this? */ + +- doInitOnStream: (Stream *)s isDecoding: (BOOL)f; +/* Internal designated initializer. Override it, but don't call it yourself. + This method name may change. */ + ++ (int) coderFormatVersion; ++ (int) coderConcreteFormatVersion; ++ (const char *) coderSignature; + +@end + +@interface Object (CoderAdditions) +- (void) encodeWithCoder: (Coder*)anEncoder; ++ newWithCoder: (Coder*)aDecoder; + +/* These methods here temporarily until ObjC runtime category bug fixed */ +- classForConnectedCoder:aRmc; ++ (void) encodeObject: anObject withConnectedCoder: aRmc; +- (id) retain; +- (void) release; +- (void) dealloc; +- (unsigned) retainCount; +- (BOOL) isProxy; + +@end + +#endif __Coder_h diff --git a/Headers/gnustep/base/Coding.h b/Headers/gnustep/base/Coding.h new file mode 100644 index 000000000..a8689f3a5 --- /dev/null +++ b/Headers/gnustep/base/Coding.h @@ -0,0 +1,57 @@ +/* Protocol for GNU Objective-C objects that can write/read to a coder + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Coding_h +#define __Coding_h + +#include + +@class Coder; + +@protocol Coding + +- (void) encodeWithCoder: (Coder*)anEncoder; ++ newWithCoder: (Coder*)aDecoder; + +/* NOTE: + + This is +newWithCoder: and not -initWithCoder: because many classes + keep track of their instances and only allow one instance of each + configuration. For example, see the designated initializers of + SocketPort, Connection, and Proxy. + + Making this +new.. instead of -init.. prevents us from having to + waste the effort of allocating space for an object to be decoded, + then immediately deallocating that space because we're just + returning a pre-existing object. + + I also like it because it makes very clear that this method is + expected to return the decoded object. This requirement would have + also been present in an -init... implementation, but the + requirement may not have been 100 percent clear by the method name. + + -mccallum */ + +@end + +#endif /* __Coding_h */ diff --git a/Headers/gnustep/base/Collecting.h b/Headers/gnustep/base/Collecting.h new file mode 100644 index 000000000..918db0c70 --- /dev/null +++ b/Headers/gnustep/base/Collecting.h @@ -0,0 +1,195 @@ +/* Protocol for Objective-C objects that hold collections of elements. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol is root of the collection protocol heirarchy. + + The protocol defines the most general interface to a + collection of elements. Elements can be added, removed, and replaced. + The contents can be tested, enumerated, and enumerated through various + filters. Elements may be objects, or any C type included in the + "elt" union given in elt.h, but all elements of a collection must be of + the same C type. +*/ + +#ifndef __Collecting_h_INCLUDE_GNU +#define __Collecting_h_INCLUDE_GNU + +#include +#include +#include + +@protocol Collecting + +// INITIALIZING; +- init; +- initWithContentsOf: (id )aCollection; + +// FREEING; +- free; +- freeObjects; + +// ADDING; +- addObject: newObject; +- addObjectIfAbsent: newObject; +- addContentsOf: (id )aCollection; +- addContentsOfIfAbsent: (id )aCollection; +- addObjectsCount: (unsigned)count, ...; + +// REMOVING; +- removeObject: oldObject; +- removeObject: oldObject ifAbsentCall: (id(*)(arglist_t))excFunc; +- removeAllOccurrencesOfObject: oldObject; +- removeContentsIn: (id )aCollection; +- removeContentsNotIn: (id )aCollection; +- uniqueContents; +- empty; + +// REPLACING; +- replaceObject: oldObject with: newObject; +- replaceObject: oldObject with: newObject + ifAbsentCall:(id(*)(arglist_t))excFunc; +- replaceAllOccurrencesOfObject: oldObject with: newObject; + +// TESTING; +- (BOOL) isEmpty; +- (BOOL) includesObject: anObject; +- (BOOL) isSubsetOf: (id )aCollection; +- (BOOL) isDisjointFrom: (id )aCollection; +- (int) compare: anObject; +- (BOOL) isEqual: anObject; +- (BOOL) contentsEqual: (id )aCollection; +- (unsigned) count; +- (unsigned) occurrencesOfObject: anObject; +- (BOOL) trueForAllObjectsByCalling: (BOOL(*)(id))aFunc; +- (BOOL) trueForAnyObjectsByCalling: (BOOL(*)(id))aFunc; +- detectObjectByCalling: (BOOL(*)(id))aFunc; +- detectObjectByCalling: (BOOL(*)(id))aFunc + ifNoneCall: (id(*)(arglist_t))excFunc; +- maxObject; +- maxObjectByCalling: (int(*)(id,id))aFunc; +- minObject; +- minObjectByCalling: (int(*)(id,id))aFunc; + +// ENUMERATING +- (void*) newEnumState; +- (BOOL) getNextObject:(id *)anObjectPtr withEnumState: (void**)enumState; +- freeEnumState: (void**)enumState; +- withObjectsCall: (void(*)(id))aFunc; +- withObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; +- injectObject: initialArgObject byCalling:(id(*)(id,id))aFunc; +- makeObjectsPerform: (SEL)aSel; +- makeObjectsPerform: (SEL)aSel with: argObject; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeMakeObjectsPerform: (SEL)aSel; +- safeMakeObjectsPerform: (SEL)aSel with: argObject; +- safeWithObjectsCall: (void(*)(id))aFunc; +- safeWithObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// FILTERED ENUMERATING; +- withObjectsTrueByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc; +- withObjectsFalseByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc; +- withObjectsTransformedByCalling: (id(*)(id))transFunc + call: (void(*)(id))destFunc; + +// COPYING +- emptyCopy; +- emptyCopyAs: (id )aCollectionClass; +- shallowCopy; +- shallowCopyAs: (id )aCollectionClass; +- copy; +- copyAs: (id )aCollectionClass; +- species; + +// ARCHIVING; +- write: (TypedStream*)aStream; +- read: (TypedStream*)aStream; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING; +- initWithType:(const char *)contentEncoding; + +// ADDING; +- addElement: (elt)newElement; +- addElementIfAbsent: (elt)newElement; +- addElementsCount: (unsigned)count, ...; + +// REMOVING; +- (elt) removeElement: (elt)oldElement; +- (elt) removeElement: (elt)oldElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; +- removeAllOccurrencesOfElement: (elt)oldElement; + +// REPLACING; +- (elt) replaceElement: (elt)oldElement with: (elt)newElement; +- (elt) replaceElement: (elt)oldElement with: (elt)newElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; +- replaceAllOccurrencesOfElement: (elt)oldElement with: (elt)newElement; + +// TESTING; +- (BOOL) includesElement: (elt)anElement; +- (unsigned) occurrencesOfElement: (elt)anElement; +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc; +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc + ifNoneCall: (elt(*)(arglist_t))excFunc; +- (elt) maxElement; +- (elt) maxElementByCalling: (int(*)(elt,elt))aFunc; +- (elt) minElement; +- (elt) minElementByCalling: (int(*)(elt,elt))aFunc; +- (BOOL) trueForAllElementsByCalling: (BOOL(*)(elt))aFunc; +- (BOOL) trueForAnyElementsByCalling: (BOOL(*)(elt))aFunc; +- (const char *) contentType; +- (BOOL) contentsAreObjects; +- (int(*)(elt,elt)) comparisonFunction; + +// ENUMERATING; +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState; +- withElementsCall: (void(*)(elt))aFunc; +- withElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag; +- (elt) injectElement: (elt)initialElement byCalling: (elt(*)(elt,elt))aFunc; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithElementsCall: (void(*)(elt))aFunc; +- safeWithElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag; + +// FILTERED ENUMERATING; +- withElementsTrueByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc; +- withElementsFalseByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc; +- withElementsTransformedByCalling: (elt(*)(elt))transFunc + call: (void(*)(elt))destFunc; + + +// BE SURE WE HAVE THESE METHODS NORMALLY PROVIDED BY Object; ++ alloc; +- (BOOL) respondsTo: (SEL)aSel; +- (BOOL) conformsTo: aProtocolObject; + +@end + +#endif /* __Collecting_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Collection.h b/Headers/gnustep/base/Collection.h new file mode 100644 index 000000000..71b2eb4a7 --- /dev/null +++ b/Headers/gnustep/base/Collection.h @@ -0,0 +1,92 @@ +/* Interface for Objective-C Collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is the abstract superclass that satisfies the Collecting + protocol, without using any instance variables. +*/ + +#ifndef __Collection_h_INCLUDE_GNU +#define __Collection_h_INCLUDE_GNU + +#include +#include +#include +#include +#include +#include +#include + +@interface Collection : Object +{ +} + ++ initialize; + +- printElement: (elt)anElement; +- printForDebugger; + +@end + +// #warning fix this macro +#define FOR_COLL(ACOLL, ELT) \ +{ \ + void *_es = [ACOLL initEnumState]; \ + while ([ACOLL getNextElement:&(ELT) withEnumState:&_es]) \ + { + +#define FOR_COLL_END \ + } \ + [ACOLL freeEnumState:_es]; \ +} + +/* The only subclassResponsibilities in Collection are: + + addElement: + removeElement: + getNextElement:withEnumState: + empty + + But subclasses may need to override the following for correctness: + + contentType + comparisonFunction + + but subclasses will want to override others as well in order to + increase efficiency, especially: + + count + + and perhaps: + + includesElement: + occurrencesOfElement: + uniqueContents + withElementsCall:whileTrue: + withElementsCall: + isEmpty + freeObjects + +*/ + +#endif /* __Collection_h_INCLUDE_GNU */ + diff --git a/Headers/gnustep/base/CollectionPrivate.h b/Headers/gnustep/base/CollectionPrivate.h new file mode 100644 index 000000000..abf841cd8 --- /dev/null +++ b/Headers/gnustep/base/CollectionPrivate.h @@ -0,0 +1,92 @@ +/* Collection definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CollectionPrivate_h_INCLUDE_GNU +#define __CollectionPrivate_h_INCLUDE_GNU + +#include +#include + +@interface Collection (ArchivingHelpers) +/* These methods should never be called except in order inside + -write: and -read: */ +- _writeInit: (TypedStream*)aStream; +- _readInit: (TypedStream*)aStream; +- _writeContents: (TypedStream*)aStream; +- _readContents: (TypedStream*)aStream; + +/* The Coding versions of the above */ +- (void) _encodeCollectionWithCoder: (Coder*) aCoder; ++ _newCollectionWithCoder: (Coder*) aCoder; +- (void) _encodeContentsWithCoder: (Coder*)aCoder; +- (void) _decodeContentsWithCoder: (Coder*)aCoder; +@end + + +/* To be used inside methods for getting the element comparison function. + This macro could be redefined when the comparison function is an + instance variable or is fixed. + I'm wondering if I should put _comparison_function back as an instance + variable in Collection. */ +#define COMPARISON_FUNCTION [self comparisonFunction] + +/* Use this for comparing elements in your implementation. */ +#define COMPARE_ELEMENTS(ELT1, ELT2) \ + ((*COMPARISON_FUNCTION)(ELT1, ELT2)) + +#define ELEMENTS_EQUAL(ELT1, ELT2) \ + (COMPARE_ELEMENTS(ELT1, ELT2) == 0) + +#define ENCODING_IS_OBJECT(ENCODING) \ + ((*(ENCODING) == _C_ID) || (*(ENCODING) == _C_CLASS)) + +/* To be used inside a method for determining if the contents are objects */ +#define CONTAINS_OBJECTS \ + (ENCODING_IS_OBJECT([self contentType])) + + +/* Error Handling */ + +#define RETURN_BY_CALLING_EXCEPTION_FUNCTION(FUNC) \ +return (*FUNC)(__builtin_apply_args()) + + +/* To be used inside a method for making sure the contents are objects. + typeof(DEFAULT_ERROR_RETURN) must be the same type as the method + returns. */ +#define CHECK_CONTAINS_OBJECTS_ERROR() \ +({if (!(CONTAINS_OBJECTS)) \ +{ \ + [self error:"in %s, requires object contents", sel_get_name(_cmd)]; \ +}}) + +/* To be used inside a method whenever a particular element isn't found */ +#define ELEMENT_NOT_FOUND_ERROR(AN_ELEMENT) \ +([self error:"in %s, element not found.", sel_get_name(_cmd)]) + +/* To be used inside a method whenever there is no element matching the + needed criteria */ +#define NO_ELEMENT_FOUND_ERROR() \ +([self error:"in %s, no element found.", sel_get_name(_cmd)]) + +#endif /* __CollectionPrivate_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/ConnectedCoder.h b/Headers/gnustep/base/ConnectedCoder.h new file mode 100644 index 000000000..2f6df13a4 --- /dev/null +++ b/Headers/gnustep/base/ConnectedCoder.h @@ -0,0 +1,66 @@ +/* Interface for coder object for distributed objects + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ConnectedCoder_h +#define __ConnectedCoder_h + +#include +#include + +/* ConnectedCoder identifiers */ +#define METHOD_REQUEST 0 +#define METHOD_REPLY 1 +#define ROOTPROXY_REQUEST 2 +#define ROOTPROXY_REPLY 3 +#define CONNECTION_SHUTDOWN 4 +#define METHODTYPE_REQUEST 5 /* these two only needed with NeXT runtime */ +#define METHODTYPE_REPLY 6 + +@class Connection; + +@interface ConnectedCoder : BinaryCoder +{ + Connection *connection; + unsigned sequence_number; + int identifier; + + /* only used for incoming ConnectedCoder's */ + id remotePort; +} + ++ newEncodingWithConnection: (Connection*)c + sequenceNumber: (int)n + identifier: (int)i; ++ newDecodingWithConnection: (Connection*)c + timeout: (int) timeout; +- dismiss; + +- connection; +- (unsigned) sequenceNumber; +- (int) identifier; + +- remotePort; + +@end + +#endif /* __ConnectedCoder_h */ diff --git a/Headers/gnustep/base/Connection.h b/Headers/gnustep/base/Connection.h new file mode 100644 index 000000000..9f29d169a --- /dev/null +++ b/Headers/gnustep/base/Connection.h @@ -0,0 +1,200 @@ +/* Interface for GNU Objective-C connection for remote object messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Connection_h_OBJECTS_INCLUDE +#define __Connection_h_OBJECTS_INCLUDE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +@class Proxy; +@class Port; +@class ConnectedCoder; + +@interface Connection : RetainingNotifier +{ + id delegate; + Port *in_port; + Port *out_port; + unsigned message_count; + Dictionary *local_targets; + Dictionary *remote_proxies; + int in_timeout; + int out_timeout; + id port_class; + int queue_dialog_interruptions; + Dictionary *incoming_const_ptrs; + Dictionary *outgoing_const_ptrs; +} + ++ setDefaultPortClass: aPortClass; ++ defaultProxyClass; ++ setDefaultProxyClass: aClass; ++ (int) defaultOutTimeout; ++ setDefaultOutTimeout: (int)to; ++ (int) defaultInTimeout; ++ setDefaultInTimeout: (int)to; +/* Setting and getting class configuration */ + ++ (int) messagesReceived; ++ (id ) allConnections; ++ (unsigned) connectionsCount; ++ (unsigned) connectionsCountWithInPort: (Port*)aPort; +/* Querying the state of all the connections */ + ++ removeObject: anObj; ++ unregisterForInvalidationNotification: anObj; +/* Use these when you're free'ing an object that may have been vended + or registered for invalidation notification */ + ++ (Connection*) newWithRootObject: anObj; ++ (Connection*) newRegisteringAtName: (const char*)n withRootObject: anObj; +/* Registering your server object on the network. + These methods create a new connection object that must be "run" in order + to start handling requests from clients. + These method names may change when we get the capability to register + ports with names after the ports have been created. */ +/* I want the second method name to clearly indicate that we're not + connecting to a pre-existing registration name, we're registering a + new name, and this method will fail if that name has already been + registered. This is why I don't like "newWithRegisteredName:" --- + it's unclear if we're connecting to another Connection that already + registered with that name. */ + ++ (Proxy*) rootProxyAtName: (const char*)name onHost: (const char*)host; ++ (Proxy*) rootProxyAtName: (const char*)name; ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort; ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort withInPort: (Port*)anInPort; +/* Get a proxy to a remote server object. + A new connection is created if necessary. */ + ++ (Connection*) newForInPort: (Port*)anInPort outPort: (Port*)anOutPort + ancestorConnection: (Connection*)ancestor; +/* This is the designated initializer for the Connection class. + You don't need to call it yourself. */ + +- (void) runConnectionWithTimeout: (int)timeout; +/* Make a connection object start listening for incoming requests. After + `timeout' milliseconds without receiving anything, return. */ + +- (void) runConnection; +/* Same as above, but never time out. */ + +- (id ) proxies; +/* When you get an invalidation notification from a connection, use + this method in order to find out if any of the proxy objects you're + using are going away. */ + +- (Proxy*) rootProxy; +/* If you somehow have a connection to a server, but don't have it's + a proxy to its root object yet, you can use this to get it. */ + +- rootObject; ++ rootObjectForInPort: (Port*)aPort; +/* For getting the root object of a connection or port */ + ++ setRootObject: anObj forInPort: (Port*)aPort; +- setRootObject: anObj; +/* Used for setting the root object of a connection that we + created without one, or changing the root object of a connection + that already has one. */ + +- (int) outTimeout; +- (int) inTimeout; +- setOutTimeout: (int)to; +- setInTimeout: (int)to; +- portClass; +- setPortClass: aPortClass; +- proxyClass; +- coderClass; +- (Port*) outPort; +- (Port*) inPort; +- delegate; +- setDelegate: anObj; +/* Querying and setting some instance variables */ + +- (Proxy*) proxyForTarget: (unsigned)target; +- addProxy: (Proxy*)aProxy; +- (BOOL) includesProxyForTarget: (unsigned)target; +- removeProxy: (Proxy*)aProxy; +- (id ) localObjects; +- addLocalObject: anObj; +- (BOOL) includesLocalObject: anObj; +- removeLocalObject: anObj; +- (retval_t) connectionForward: (Proxy*)object : (SEL)sel : (arglist_t)frame; +- (const char *) _typeForSelector: (SEL)sel remoteTarget: (unsigned)target; +- (Dictionary*) _incomingConstPtrs; +- (Dictionary*) _outgoingConstPtrs; +/* Only subclassers and power-users need worry about these */ + +@end + +@protocol ConnectedCoding ++ (void) encodeObject: anObj withConnectedCoder: aRmc; +@end + +@interface Object (ConnectionDelegate) +- (Connection*) connection: ancestorConn didConnect: newConn; +/* If the delegate responds to this method, it will be used to ask the + delegate's permission to establish a new connection from the old one. + Often this is used so that the delegate can register for invalidation + notification on new child connections. + Normally return newConn. */ +@end + +#if 0 /* Put in Coder.m until ObjC runtime category-loading bug is fixed */ + +@interface Object (ConnectionRequests) +- classForConnectedCoder: aRmc; +/* Must return the class that will be created on the remote side + of the connection. + Used by the remote objects system to determine how the receiver + should be encoded across the network. + In general, you can: + return [Proxy class] to send a proxy of the receiver; + return [self class] to send the receiver bycopy. + The Object class implementation returns [Proxy class]. */ ++ (void) encodeObject: anObject withConnectedCoder: aRmc; +/* This message is sent to the class returned by -classForConnectedCoder: + The Proxy class implementation encodes a proxy for anObject. + The Object class implementation encodes the receiver itself. */ +@end + +@interface Object (Retaining) +/* Make sure objects don't crash when you send them messages. + These implementations, however, do nothing. */ +@end + +#endif /* 0 Put in Coder.m */ + +#define CONNECTION_DEFAULT_TIMEOUT 15000 /* in milliseconds */ + +#endif /* __Connection_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/DelegatePool.h b/Headers/gnustep/base/DelegatePool.h new file mode 100644 index 000000000..bc6be226f --- /dev/null +++ b/Headers/gnustep/base/DelegatePool.h @@ -0,0 +1,68 @@ +/* Interface for Objective-C "collection of delegates" object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Using this object, a delegator can have an arbitrary number of + delegates. Send a message to this object and the message will get + forwarded to the delegates on the list. */ + +#ifndef __DelegatePool_h_OBJECTS_INCLUDE +#define __DelegatePool_h_OBJECTS_INCLUDE + +#include +#include + +/* Available sending behaviors */ +enum DelegatePoolSendBehavior {SEND_TO_ALL = 0, + SEND_TO_FIRST_RESPONDER, + SEND_UNTIL_YES, + SEND_UNTIL_NO}; + +@interface DelegatePool +{ + struct objc_class *isa; + @public + unsigned char _send_behavior; + Array *_list; +} + +// CREATING AND FREEING; ++ alloc; ++ new; +- init; +- free; + +// MANIPULATING COLLECTION OF DELEGATES; +- delegatePoolAddObject: anObject; +- delegatePoolAddObjectIfAbsent: anObject; +- delegatePoolRemoveObject: anObject; +- (BOOL) delegatePoolIncludesObject: anObject; +- delegatePoolCollection; +- (unsigned char) delegatePoolSendBehavior; +- delegatePoolSetSendBehavior: (unsigned char)b; + +// FOR PASSING ALL OTHER MESSAGES TO DELEGATES; +- forward:(SEL)aSel :(arglist_t)argFrame; + +@end + +#endif /* __DelegatePool_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/Dictionary.h b/Headers/gnustep/base/Dictionary.h new file mode 100644 index 000000000..fc28dda41 --- /dev/null +++ b/Headers/gnustep/base/Dictionary.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C Dictionary collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Dictionary_h_INCLUDE_GNU +#define __Dictionary_h_INCLUDE_GNU + +#include +#include + +@interface Dictionary : KeyedCollection +{ + coll_cache_ptr _contents_hash; // a hashtable to hold the contents; + int (*_comparison_function)(elt,elt); +} + + +@end + +#endif /* __Dictionary_h_INCLUDE_GNU */ + diff --git a/Headers/gnustep/base/EltNode-h b/Headers/gnustep/base/EltNode-h new file mode 100644 index 000000000..ce2cdb695 --- /dev/null +++ b/Headers/gnustep/base/EltNode-h @@ -0,0 +1,41 @@ +/* Code for interface of Objective-C EltNode objects + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 + + This file is part of the GNU Objective-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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file gets included in all the ...EltNode.h files + Doing this silly #include stuff is a poor substitute for multiple + inheritance. sigh. + + Pattern: + + @interface FooEltNode : FooNode + #include + @end +*/ + + + +{ + elt _element; + int (*_elt_comparison_function)(elt,elt); +} +- (int(*)(elt,elt)) comparisonFunction; diff --git a/Headers/gnustep/base/EltNode-m b/Headers/gnustep/base/EltNode-m new file mode 100644 index 000000000..69df85904 --- /dev/null +++ b/Headers/gnustep/base/EltNode-m @@ -0,0 +1,134 @@ +/* Code for implementation for Objective-C EltNode objects + Copyright (C) 1993 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 + + This file is part of the GNU Objective-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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file gets included in all the ...EltNode.m files. + Doing this silly #include stuff is a poor substitute for multiple + inheritance. sigh. + + Pattern: + + @implementation FooEltNode : FooNode + #include + @end +*/ + +#include + +- initElement: (elt)anElement + encoding: (const char *)eltEncoding +{ + [super init]; + _element = anElement; + _elt_comparison_function = elt_get_comparison_function(eltEncoding); + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)aCoder +{ + const char *encoding; + + [super encodeWithCoder:aCoder]; + encoding = elt_get_encoding(_elt_comparison_function); + [aCoder encodeValueOfType:@encode(char*) at:&encoding + withName:"EltNode Content Type Encoding"]; + [aCoder encodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &_element) + withName:"EltNode Content Element"]; +} + +- (elt*) _elementDataPtr +{ + return &_element; +} + +- (int(**)(elt,elt)) _eltComparisonFunctionPtr +{ + return &_elt_comparison_function; +} + ++ newWithCoder: (Coder*)aCoder +{ + id n; + char *encoding; + + n = [super newWithCoder:aCoder]; + [aCoder decodeValueOfType:@encode(char*) + at:&encoding + withName:NULL]; + *[n _eltComparisonFunctionPtr] = elt_get_comparison_function(encoding); + [aCoder decodeValueOfType:encoding + at:[n _elementDataPtr] + withName:NULL]; + return n; +} + +- write: (TypedStream*)aStream +{ + const char *encoding; + + [super write:aStream]; + encoding = elt_get_encoding(_elt_comparison_function); + objc_write_type(aStream, @encode(char*), &encoding); + objc_write_types(aStream, encoding, + elt_get_ptr_to_member(encoding, &_element)); + return self; +} + +- read: (TypedStream*)aStream +{ + char *encoding; + + [super read:aStream]; + objc_read_type(aStream, @encode(char*), &encoding); + _elt_comparison_function = elt_get_comparison_function(encoding); + objc_read_type(aStream, encoding, + elt_get_ptr_to_member(encoding,&_element)); + return self; +} + +- (int(*)(elt,elt)) comparisonFunction +{ + return _elt_comparison_function; +} + +- (elt) elementData +{ + return _element; +} + +- (int) compare: anotherObject +{ + /* perhaps we should do more checking first */ + return _elt_comparison_function(_element, [anotherObject elementData]); +} + +- printForDebugger +{ + elt_fprintf_elt(stdout, + elt_get_encoding(_elt_comparison_function), + _element); + printf("\n"); + return self; +} diff --git a/Headers/gnustep/base/EltNodeCollector.h b/Headers/gnustep/base/EltNodeCollector.h new file mode 100644 index 000000000..4f850574a --- /dev/null +++ b/Headers/gnustep/base/EltNodeCollector.h @@ -0,0 +1,67 @@ +/* Interface for Objective-C EltNodeCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* EltNodeCollector */ + +#ifndef __EltNodeCollector_h_INCLUDE_GNU +#define __EltNodeCollector_h_INCLUDE_GNU + +#include +#include + +/* Protocol for a node that also holds an element */ +@protocol EltHolding +- initElement: (elt)anElement + encoding: (const char *)eltEncoding; +- (elt) elementData; +@end + + +/* It's is a bit unfortunate that we insist that the underlying + collector conform to IndexedCollecting. */ + +@interface EltNodeCollector : IndexedCollection +{ + @private + id _contents_collector; + id _node_class; + int (*_comparison_function)(elt,elt); +} + + +- initWithType: (const char *)contentEncoding + nodeCollector: aNodeCollector + nodeClass: aNodeClass; + +// The class of the autocreated link objects, must conform to ; +- eltNodeClass; + +// Getting the underlying node collector that holds the contents; +- contentsCollector; + +// Finding the node that contains anElement; +- (id ) eltNodeWithElement: (elt)anElement; + +@end + +#endif /* __EltNodeCollector_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/GapArray.h b/Headers/gnustep/base/GapArray.h new file mode 100644 index 000000000..e39f89cde --- /dev/null +++ b/Headers/gnustep/base/GapArray.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C GapArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __GapArray_h_INCLUDE_GNU +#define __GapArray_h_INCLUDE_GNU + +#include +#include + +@interface GapArray : Array +{ + @public + unsigned _gap_start; /* start of gap */ + unsigned _gap_size; /* size of gap */ +} + +@end + +#endif /* __GapArray_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/GapArrayPrivate.h b/Headers/gnustep/base/GapArrayPrivate.h new file mode 100644 index 000000000..00d8c6a32 --- /dev/null +++ b/Headers/gnustep/base/GapArrayPrivate.h @@ -0,0 +1,89 @@ +/* GapArray definitions for the use of subclass implementations + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + Copyright (C) 1993,1994 Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __GapArrayPrivate_h_INCLUDE_GNU +#define __GapArrayPrivate_h_INCLUDE_GNU + +#include +#include +#include + +#define GAP_TO_BASIC(INDEX) \ + ({ unsigned int __idx = (INDEX); \ + __idx >= self->_gap_start \ + ? __idx+self->_gap_size : __idx; }) + +#define BASIC_TO_GAP(INDEX) \ + ({ unsigned int __idx = (INDEX); \ + __idx < self->_gap_start \ + ? __idx : __idx-self->_gap_size; }) + +static inline void +gapMoveGapTo (GapArray* self, unsigned index) +{ + int i; + assert (index <= self->_capacity); + if (index < self->_gap_start) + { +#ifndef STABLE_MEMCPY + int b = index + self->_gap_size; + for (i = self->_gap_start + self->_gap_size - 1; i >= b; i--) + self->_contents_array[i] = self->_contents_array[i - self->_gap_size]; +#else + memcpy (self->_contents_array + index + self->_gap_size, + self->_contents_array + index, + self->_gap_start - index) +#endif + } + else + { +#ifndef STABLE_MEMCPY + for(i = self->_gap_start; i != index; i++) + self->_contents_array[i] = self->_contents_array[i - self->_gap_size]; +#else + memcpy (self->_contents_array + self->_gap_start, + self->_contents_array + self->_gap_start + self->_gap_size, + index - self->_gap_start); +#endif + } + self->_gap_start = index; +} + +static inline void +gapMakeHoleAt(GapArray *self, unsigned index) +{ + gapMoveGapTo (self, index); + self->_gap_start += 1; + self->_gap_size -= 1; +} + +static inline void +gapFillHoleAt(GapArray *self, unsigned index) +{ + gapMoveGapTo (self, index); + self->_gap_size += 1; +} + +#endif /* __GapArrayPrivate_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Heap.h b/Headers/gnustep/base/Heap.h new file mode 100644 index 000000000..d3592c4e3 --- /dev/null +++ b/Headers/gnustep/base/Heap.h @@ -0,0 +1,42 @@ +/* Interface for Objective-C Heap collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Heap_h_INCLUDE_GNU +#define __Heap_h_INCLUDE_GNU + +#include +#include + +@interface Heap : Array +{ +} + +- addElement: (elt)anElement; +- (elt) removeFirstElement; + +- heapifyFromIndex: (unsigned)index; +- heapify; + +@end + +#endif /* __Heap_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/IndexedCollecting.h b/Headers/gnustep/base/IndexedCollecting.h new file mode 100644 index 000000000..d8cb82331 --- /dev/null +++ b/Headers/gnustep/base/IndexedCollecting.h @@ -0,0 +1,203 @@ +/* Protocol for Objective-C objects that hold elements accessible by index + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol inherits from the + protocol. + + The protocol defines the interface to a + collection of elements that are accessible by a key that is an index, + where the indeces in a collection are a contiguous series of unsigned + integers beginning at 0. This is the root of the protocol heirarchy + for all collections that hold their elements in some order. Elements + may be accessed, inserted, replaced and removed by their index. +*/ + +#ifndef __IndexedCollecting_h_OBJECTS_INCLUDE +#define __IndexedCollecting_h_OBJECTS_INCLUDE + +#include +#include + +typedef struct _IndexRange { + unsigned start; + unsigned end; +} IndexRange; +/* Includes elements from start to end-1 Is this ugly? + I do this so I can specify a NULL range + How about this instead: + typedef struct _IndexRange { + unsigned start; + unsigned length; + } +*/ + +//#define MakeIndexRange(START,END) \ +// ({ IndexRange __ir = {(START), (END)}; __ir; }) +// USE: ((IndexRange) {(START),(END)}) + +#define IndexRangeInside(RANGE1,RANGE2) \ + ({IndexRange __a=(RANGE1), __b=(RANGE2); \ + __a.start<=__b.start && __a.end>=__b.end;}) + + +@protocol IndexedCollecting + +// ADDING; +- insertObject: newObject atIndex: (unsigned)index; +- insertObject: newObject before: oldObject; +- insertObject: newObject after: oldObject; +- insertContentsOf: (id )aCollection atIndex: (unsigned)index; +- appendObject: newObject; +- prependObject: newObject; +- appendContentsOf: (id )aCollection; +- prependContentsOf: (id )aCollection; + +// REPLACING AND SWAPPING +- replaceObjectAtIndex: (unsigned)index with: newObject; +- replaceRange: (IndexRange)aRange with: (id )aCollection; +- replaceRange: (IndexRange)aRange using: (id )aCollection; +- swapAtIndeces: (unsigned)index1 : (unsigned)index2; + +// REMOVING +- removeObjectAtIndex: (unsigned)index; +- removeFirstObject; +- removeLastObject; +- removeRange: (IndexRange)aRange; + +// GETTING MEMBERS BY INDEX; +- objectAtIndex: (unsigned)index; +- firstObject; +- lastObject; + +// GETTING MEMBERS BY NEIGHBOR; +- successorOfObject: anObject; +- predecessorOfObject: anObject; + +// GETTING INDICES BY MEMBER; +- (unsigned) indexOfObject: anObject; +- (unsigned) indexOfObject: anObject + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange; +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; + +// TESTING; +- (BOOL) includesIndex: (unsigned)index; +- (BOOL) contentsEqualInOrder: (id )aColl; +- (unsigned) indexOfFirstDifference: (id )aColl; +- (unsigned) indexOfFirstIn: (id )aColl; +- (unsigned) indexOfFirstNotIn: (id )aColl; + +// ENUMERATING; +- (BOOL) getPrevObject: (id*)anIdPtr withEnumState: (void**)enumState; +- withObjectsInRange: (IndexRange)aRange call:(void(*)(id))aFunc; +- withObjectsInReverseCall: (void(*)(id))aFunc; +- withObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithObjectsInReverseCall: (void(*)(id))aFunc; +- safeWithObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// SORTING; +- sortContents; +- sortObjectsByCalling: (int(*)(id,id))aFunc; +- sortAddObject: newObject; +- sortAddObject: newObject byCalling: (int(*)(id,id))aFunc; + + +// NON-OBJECT MESSAGE NAMES; + +// ADDING; +- appendElement: (elt)newElement; +- prependElement: (elt)newElement; +- insertElement: (elt)newElement atIndex: (unsigned)index; +- insertElement: (elt)newElement before: (elt)oldElement; +- insertElement: (elt)newElement after: (elt)oldElement; + +// REMOVING AND REPLACING; +- (elt) removeElementAtIndex: (unsigned)index; +- (elt) removeFirstElement; +- (elt) removeLastElement; +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement; + +// GETTING ELEMENTS BY INDEX; +- (elt) elementAtIndex: (unsigned)index; +- (elt) firstElement; +- (elt) lastElement; + +// GETTING MEMBERS BY NEIGHBOR; +- (elt) successorOfElement: (elt)anElement; +- (elt) predecessorOfElement: (elt)anElement; + +// GETTING INDICES BY MEMBER; +- (unsigned) indexOfElement: (elt)anElement; +- (unsigned) indexOfElement: (elt)anElement + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange; +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; + +// ENUMERATING; +- (BOOL) getPrevElement:(elt*)anElementPtr withEnumState: (void**)enumState; +- withElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc; +- withElementsInReverseCall: (void(*)(elt))aFunc; +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc; +- safeWithElementsInReverseCall: (void(*)(elt))aFunc; +- safeWithElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag; + +// SORTING; +- sortElementsByCalling: (int(*)(elt,elt))aFunc; +- sortAddElement: (elt)newElement; +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc; + +@end + +/* Most methods in the KeyedCollecting protocol that mention a key are + duplicated in the IndexedCollecting protocol, with their names + modified to reflect that the "key" now must be an unsigned integer, + (an "index"). The programmer should be able to use either of the + corresponding method names to the same effect. + + The new methods are provided in the IndexedCollecting protocol for: + 1) Better type checking for when an unsigned int is required. + 2) More intuitive method names. + + IndexedCollecting KeyedCollecting + ---------------------------------------------------------------------- + insertObject:atIndex insertObject:atKey: + replaceObjectAtIndex:with: replaceObjectAtKey:with: + removeObjectAtIndex: removeObjectAtKey: + objectAtIndex: objectAtKey: + includesIndex: includesKey: + + insertElement:atIndex insertElement:atKey: + replaceElementAtIndex:with: replaceElementAtKey:with: + removeElementAtIndex: removeElementAtKey: + elementAtIndex: elementAtKey: + +*/ + +#endif /* __IndexedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/IndexedCollection.h b/Headers/gnustep/base/IndexedCollection.h new file mode 100644 index 000000000..3e7a4f758 --- /dev/null +++ b/Headers/gnustep/base/IndexedCollection.h @@ -0,0 +1,66 @@ +/* Interface for Objective-C Sequential Collection object. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IndexedCollection_h_INCLUDE_GNU +#define __IndexedCollection_h_INCLUDE_GNU + +#include +#include +#include + +@interface IndexedCollection : KeyedCollection + +@end + +/* The only subclassResponsibilities in IndexedCollection are: + + insertElement:atIndex: + removeElementAtIndex: + elementAtIndex: + + but subclass will want to override others as well in order to + increase efficiency. The following are especially important if + the subclass's implementation of "elementAtIndex:" is not efficient: + + replaceElementAtIndex:with: + swapAtIndeces:: + shallowCopyReplaceFrom:to:with: + sortAddElement:byCalling: + removeElement: + firstElement + lastElement + shallowCopyFrom:to: + withElementsCall:whileTrue: + withElementsInReverseCall:whileTrue: + + and perhaps: + + appendElement: + prependElement: + indexOfElement: + withElementsInReverseCall: + +*/ + + +#endif /* __IndexedCollection_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/IndexedCollectionPrivate.h b/Headers/gnustep/base/IndexedCollectionPrivate.h new file mode 100644 index 000000000..02bf8044a --- /dev/null +++ b/Headers/gnustep/base/IndexedCollectionPrivate.h @@ -0,0 +1,47 @@ +/* IndexedCollection definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IndexedCollectionPrivate_h_INCLUDE_GNU +#define __IndexedCollectionPrivate_h_INCLUDE_GNU + +#include +#include + +/* To be used inside a method for making sure that index + is not above range. +*/ +#define CHECK_INDEX_RANGE_ERROR(INDEX, OVER) \ +({if (INDEX >= OVER) \ + [self error:"in %s, index out of range", sel_get_name(_cmd)];}) + + +/* For use with subclasses of IndexedCollections that allow elements to + be added, but not added at particular indices---the collection itself + determines the order. +*/ +#define INSERTION_ERROR() \ +([self error:"in %s, this collection does not allow insertions", \ + sel_get_name(aSel)];) + + +#endif /* __IndexedCollectionPrivate_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/InvalidationListening.h b/Headers/gnustep/base/InvalidationListening.h new file mode 100644 index 000000000..3748381db --- /dev/null +++ b/Headers/gnustep/base/InvalidationListening.h @@ -0,0 +1,37 @@ +/* Protocol for GNU Objective-C objects that understand an invalidation msg + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __InvalidationListening_h_OBJECTS_INCLUDE +#define __InvalidationListening_h_OBJECTS_INCLUDE + +/* This protocol is just temporary. It will disappear when GNU writes + a more general notification system. + It is not recommended that you use it in your code. */ + +@protocol InvalidationListening + +- senderIsInvalid: sender; + +@end + +#endif /* __InvalidationListening_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/KeyedCollecting.h b/Headers/gnustep/base/KeyedCollecting.h new file mode 100644 index 000000000..8f3335986 --- /dev/null +++ b/Headers/gnustep/base/KeyedCollecting.h @@ -0,0 +1,116 @@ +/* Protocol for Objective-C objects holding (keyElement,contentElement) pairs. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol inherits from the protocol. + + The protocol defines the interface to a + collection of elements that are accessible by a key, where the key is + some unique element. Pairs of (key element, content element) may be + added, removed and replaced. The keys and contents may be tested, + enumerated and copied. +*/ + +#ifndef __KeyedCollecting_h_OBJECTS_INCLUDE +#define __KeyedCollecting_h_OBJECTS_INCLUDE + +#include +#include + +@protocol KeyedCollecting + +// ADDING; +- putObject: newContentObject atKey: (elt)aKey; + +// REPLACING AND SWAPPING; +- replaceObjectAtKey: (elt)aKey with: newContentObject; +- swapAtKeys: (elt)key1 : (elt)key2; + +// REMOVING; +- removeObjectAtKey: (elt)aKey; + +// GETTING ELEMENTS AND KEYS; +- objectAtKey: (elt)aKey; +- keyObjectOfObject: aContentObject; + +// TESTING; +- (BOOL) includesKey: (elt)aKey; + +// ENUMERATIONS; +- withKeyObjectsCall: (void(*)(id))aFunc; +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc; +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithKeyObjectsCall: (void(*)(id))aFunc; +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc; +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING; +- initWithType: (const char *)contentsEncoding + keyType: (const char *)keyEncoding; +- initKeyType: (const char *)keyEncoding; + +// ADDING; +- putElement: (elt)newContentElement atKey: (elt)aKey; + +// REPLACING; +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement; +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// REMOVING; +- (elt) removeElementAtKey: (elt)aKey; +- (elt) removeElementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// GETTING ELEMENTS AND KEYS; +- (elt) elementAtKey: (elt)aKey; +- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc; +- (elt) keyElementOfElement: (elt)aContentObject; +- (elt) keyElementOfElement: (elt)aContentObject + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// TESTING; +- (const char *) keyType; + +// ENUMERATING; +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState; +- withKeyElementsCall: (void(*)(elt))aFunc; +- withKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc; +- withKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc + whileTrue: (BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithKeyElementsCall: (void(*)(elt))aFunc; +- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc; +- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc + whileTrue: (BOOL *)flag; + +@end + +#endif /* __KeyedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/KeyedCollection.h b/Headers/gnustep/base/KeyedCollection.h new file mode 100644 index 000000000..2e77dd700 --- /dev/null +++ b/Headers/gnustep/base/KeyedCollection.h @@ -0,0 +1,45 @@ +/* Interface for Objective-C KeyedCollection collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __KeyedCollection_h_INCLUDE_GNU +#define __KeyedCollection_h_INCLUDE_GNU + +#include +#include +#include + +@interface KeyedCollection : Collection + +@end + +/* The only subclassResponsibilities in IndexedCollection are: + + keyDescription + insertElement:atKey: + removeElementAtKey: + elementAtKey: + includesKey: + getNextKey:content:withEnumState: +*/ + +#endif /* __KeyedCollection_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/LinkedList.h b/Headers/gnustep/base/LinkedList.h new file mode 100644 index 000000000..b6a2f7e20 --- /dev/null +++ b/Headers/gnustep/base/LinkedList.h @@ -0,0 +1,48 @@ +/* Interface for Objective-C LinkedList collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedList_h_INCLUDE_GNU +#define __LinkedList_h_INCLUDE_GNU + +#include +#include + +/* The protocol defines the interface to an object + that may be an element in a LinkedList. +*/ +@protocol LinkedListComprising +- nextLink; +- prevLink; +- setNextLink: (id )aLink; +- setPrevLink: (id )aLink; +@end + +@interface LinkedList : IndexedCollection +{ + id _first_link; + unsigned int _count; +} + +@end + +#endif /* __LinkedList_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/LinkedListEltNode.h b/Headers/gnustep/base/LinkedListEltNode.h new file mode 100644 index 000000000..d2d0a153e --- /dev/null +++ b/Headers/gnustep/base/LinkedListEltNode.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C LinkedListEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedListEltNode_h_INCLUDE_GNU +#define __LinkedListEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface LinkedListEltNode : LinkedListNode +#include +@end + +#endif /* __LinkedListEltNode_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/LinkedListNode.h b/Headers/gnustep/base/LinkedListNode.h new file mode 100644 index 000000000..c09229e5b --- /dev/null +++ b/Headers/gnustep/base/LinkedListNode.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C LinkedListNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedListNode_h_INCLUDE_GNU +#define __LinkedListNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface LinkedListNode : Object +{ + id _next; + id _prev; +} +@end + +#endif /* __LinkedListNode_h_INCLUDE_GNU */ + diff --git a/Headers/gnustep/base/Lock.h b/Headers/gnustep/base/Lock.h new file mode 100644 index 000000000..7a3cd2b92 --- /dev/null +++ b/Headers/gnustep/base/Lock.h @@ -0,0 +1,35 @@ +/* Interface for GNU Objective-C mutex lock + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Lock_h_OBJECTS_INCLUDE +#define __Lock_h_OBJECTS_INCLUDE + +#include +#include + +@interface Lock : Object +{ +} +@end + +#endif /* __Lock_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/Locking.h b/Headers/gnustep/base/Locking.h new file mode 100644 index 000000000..4dfab0714 --- /dev/null +++ b/Headers/gnustep/base/Locking.h @@ -0,0 +1,35 @@ +/* Protocol for GNU Objective-C mutex locks + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Locking_h_INCLUDE_GNU +#define __Locking_h_INCLUDE_GNU + +#include +#include + +@protocol Locking +- (void) lock; +- (void) unlock; +@end + +#endif /* __Locking_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Magnitude.h b/Headers/gnustep/base/Magnitude.h new file mode 100644 index 000000000..821ee42be --- /dev/null +++ b/Headers/gnustep/base/Magnitude.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C Magnitude object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Magnitude_h_INCLUDE_GNU +#define __Magnitude_h_INCLUDE_GNU + +#include +#include +#include + +@interface Magnitude : Object + +@end + +#endif /* __Magnitude_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/MappedCollector.h b/Headers/gnustep/base/MappedCollector.h new file mode 100644 index 000000000..6856d6eb3 --- /dev/null +++ b/Headers/gnustep/base/MappedCollector.h @@ -0,0 +1,41 @@ +/* Interface for Objective-C MappedCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MappedCollector_h_INCLUDE_GNU +#define __MappedCollector_h_INCLUDE_GNU + +#include +#include + +@interface MappedCollector : KeyedCollection +{ + id _map; + id _domain; +} + +- initCollection: (id )aDomain + map: (id )aMap; + +@end + +#endif /* __MappedCollector_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/MemoryStream.h b/Headers/gnustep/base/MemoryStream.h new file mode 100644 index 000000000..3f057414b --- /dev/null +++ b/Headers/gnustep/base/MemoryStream.h @@ -0,0 +1,55 @@ +/* Interface for GNU Objective C memory stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MemoryStream_h_OBJECTS_INCLUDE +#define __MemoryStream_h_OBJECTS_INCLUDE + +#include +#include + +@interface MemoryStream : Stream +{ + int type; + char *buffer; + int size; + int eofPosition; + int prefix; + int position; +} + +- initWithSize: (unsigned)s; +- (char *) streamBuffer; +- (unsigned) streamBufferLength; +- (unsigned) streamPrefix; +- (unsigned) streamEofPosition; +- (void) setStreamBufferSize: (unsigned)s; + +/* xxx This interface will change */ +- _initOnMallocBuffer: (char*)b + size: (unsigned)s /* size of malloc'ed buffer */ + eofPosition: (unsigned)l /* length of buffer with data for reading */ + prefix: (unsigned)p /* reset for this position */ + position: (unsigned)i; /* current position for reading/writing */ +@end + +#endif /* __MemoryStream_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/Ordering.h b/Headers/gnustep/base/Ordering.h new file mode 100644 index 000000000..ed34bf333 --- /dev/null +++ b/Headers/gnustep/base/Ordering.h @@ -0,0 +1,47 @@ +/* Protocol for Objective-C objects that can be ordered. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Ordering_h_INCLUDE_GNU +#define __Ordering_h_INCLUDE_GNU + +#include +#include + +@protocol Ordering + +- (int) compare: anObject; + +- (BOOL) greaterThan: anObject; +- (BOOL) greaterThanOrEqual: anObject; + +- (BOOL) lessThan: anObject; +- (BOOL) lessThanOrEqual: anObject; + +- (BOOL) between: firstObject and: secondObject; + +- maximum: anObject; +- minimum: anObject; + +@end + +#endif /* __Ordering_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Port.h b/Headers/gnustep/base/Port.h new file mode 100644 index 000000000..48c948f6c --- /dev/null +++ b/Headers/gnustep/base/Port.h @@ -0,0 +1,61 @@ +/* Interface for abstract superclass port for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Port_h_OBJECTS_INCLUDE +#define __Port_h_OBJECTS_INCLUDE + +#include +#include +#include + +@class Connection; + +@interface Port : RetainingNotifier + +/* xxx These will probably change */ ++ newRegisteredPortWithName: (const char *)n; ++ newPortFromRegisterWithName: (const char *)n onHost: (const char *)host; ++ newPort; + +/* xxx These sending and receiving interfaces will change */ + +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*) remote; +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*)remote + timeout: (int) milliseconds; + +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote; +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote + timeout: (int) milliseconds; + +- (BOOL) isSoft; + +- (unsigned) hash; +- (BOOL) isEqual: anotherPort; + +@end + +#endif /* __Port_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/Proxy.h b/Headers/gnustep/base/Proxy.h new file mode 100644 index 000000000..768be4481 --- /dev/null +++ b/Headers/gnustep/base/Proxy.h @@ -0,0 +1,82 @@ +/* Interface for GNU Objective-C proxy for remote objects messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Proxy_h_OBJECTS_INCLUDE +#define __Proxy_h_OBJECTS_INCLUDE + +#include +#include +#include + +@class ConnectedCoder; + +@interface Proxy +{ +@public + struct objc_class *isa; + unsigned target; + Connection *connection; + unsigned retain_count; +#if NeXT_runtime + coll_cache_ptr _method_types; + Protocol *protocol; +#endif +} + +/* xxx Change name to newForTarget:connection: */ ++ newForRemote: (unsigned)target connection: (Connection*)c; + +- self; +#if NeXT_runtime ++ class; +#else ++ (Class*) class; +#endif + +- invalidateProxy; +- (BOOL) isProxy; +- (unsigned) targetForProxy; +- connectionForProxy; + +- forward: (SEL)aSel :(arglist_t)frame; + +- classForConnectedCoder: aRmc; ++ (void) encodeObject: anObject withConnectedCoder: aRmc; + ++ newWithCoder: aCoder; +- (void) encodeWithCoder: aCoder; + +/* Only needed with NeXT runtime. */ +- (const char *) selectorTypeForProxy: (SEL)selector; + +@end + +@interface Object (IsProxy) +- (BOOL) isProxy; +@end + +@interface Protocol (RemoteCoding) +- classForConnectedCoder: aRmc; +@end + +#endif /* __Proxy_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/Queue.h b/Headers/gnustep/base/Queue.h new file mode 100644 index 000000000..f845ef99b --- /dev/null +++ b/Headers/gnustep/base/Queue.h @@ -0,0 +1,41 @@ +/* Interface for Objective-C Queue object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Queue_h_INCLUDE_GNU +#define __Queue_h_INCLUDE_GNU + +#include +#include + +@interface Queue : CircularArray + +- enqueueObject: newObject; +- dequeueObject; + +// NON-OBJECT MESSAGE NAMES; +- enqueueElement: (elt)newElement; +- (elt) dequeueElement; + +@end + +#endif /* __Queue_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RBTree.h b/Headers/gnustep/base/RBTree.h new file mode 100644 index 000000000..7725baaee --- /dev/null +++ b/Headers/gnustep/base/RBTree.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C Red-Black Tree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTree_h_INCLUDE_GNU +#define __RBTree_h_INCLUDE_GNU + +#include +#include + +@protocol RBTreeComprising +- (BOOL) isRed; +- setRed; +- setBlack; +@end + +@interface RBTree : BinaryTree + +@end + +#endif /* __RBTree_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RBTreeEltNode.h b/Headers/gnustep/base/RBTreeEltNode.h new file mode 100644 index 000000000..0606a6f71 --- /dev/null +++ b/Headers/gnustep/base/RBTreeEltNode.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C RBTreeEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTreeEltNode_h_INCLUDE_GNU +#define __RBTreeEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface RBTreeEltNode : RBTreeNode +#include +@end + +#endif /* __RBTreeEltNode_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RBTreeNode.h b/Headers/gnustep/base/RBTreeNode.h new file mode 100644 index 000000000..e2eb4d6d7 --- /dev/null +++ b/Headers/gnustep/base/RBTreeNode.h @@ -0,0 +1,37 @@ +/* Interface for Objective-C RBTreeNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTreeNode_h_INCLUDE_GNU +#define __RBTreeNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface RBTreeNode : BinaryTreeNode +{ + BOOL _red; +} +@end + +#endif /* __RBTreeNode_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RNGAdditiveCongruential.h b/Headers/gnustep/base/RNGAdditiveCongruential.h new file mode 100644 index 000000000..fd5d07e27 --- /dev/null +++ b/Headers/gnustep/base/RNGAdditiveCongruential.h @@ -0,0 +1,44 @@ +/* Interface for additive congruential pseudo-random num generating + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Additive Congruential Method, + from Robert Sedgewick, "Algorithms" */ + +#ifndef __RNGAdditiveCongruential_h_INCLUDE_GNU +#define __RNGAdditiveCongruential_h_INCLUDE_GNU + +#include +#include + +@interface RNGAdditiveCongruential : Object +{ + long *table; + int table_size; + int tap1; + int tap2; + int index; +} + +@end + +#endif /* __RNGAdditiveCongruential_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RNGBerkeley.h b/Headers/gnustep/base/RNGBerkeley.h new file mode 100644 index 000000000..bfa67e24c --- /dev/null +++ b/Headers/gnustep/base/RNGBerkeley.h @@ -0,0 +1,74 @@ +/* Interface for Berkeley random()-compatible generation for Objective-C + + Reworked by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RNGBerkeley_h_INCLUDE_GNU +#define __RNGBerkeley_h_INCLUDE_GNU + +/* + * Copyright (c) 1983 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * It was reworked for the GNU Objective-C Library by R. Andrew McCallum + */ + +#include +#include + +@interface RNGBerkeley : Object +{ + int foo[2]; + long int randtbl[32]; /* Size must match DEG_3 + 1 from RNGBerkeley.m */ + long int *fptr; + long int *rptr; + long int *state; + int rand_type; + int rand_deg; + int rand_sep; + long int *end_ptr; +} + +- (void) _srandom: (unsigned int)x; +- (void*) _initstateSeed: (unsigned int)seed + state: (void*)arg_state + size: (size_t)n; +- (void*) _setstate: (void*)arg_state; + +@end + +#endif /* __RNGBerkeley_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Random.h b/Headers/gnustep/base/Random.h new file mode 100644 index 000000000..c800c16a1 --- /dev/null +++ b/Headers/gnustep/base/Random.h @@ -0,0 +1,69 @@ +/* Interface for Objective-C object providing randoms in uniform distribution + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Random_h_INCLUDE_GNU +#define __Random_h_INCLUDE_GNU + +#include +#include + +@interface Random : Object +{ + id rng; +} + ++ initialize; ++ (id ) defaultRandomGeneratorClass; ++ setDefaultRandomGeneratorClass: (id )aRNG; + ++ (float) chiSquareOfRandomGenerator: (id )aRNG + iterations: (int)n + range: (long)r; ++ (float) chiSquareOfRandomGenerator: (id )aRNG; + +- init; + +- setRandomSeedFromClock; +- setRandomSeed: (long)seed; + +- (long) randomInt; +- (long) randomIntBetween: (long)lowBound and: (long)highBound; +- (long) randomDie: (long)numSides; /* between 0 and numSides-1 */ + +- (BOOL) randomCoin; +- (BOOL) randomCoinWithProbability: (double)p; + +- (float) randomFloat; +- (float) randomFloatBetween: (float)lowBound and: (float)highBound; +- (float) randomFloatProbability; + +- (double) randomDouble; +- (double) randomDoubleBetween: (double)lowBound and: (double)highBound; +- (double) randomDoubleProbability; + +- read: (TypedStream*)aStream; +- write: (TypedStream*)aStream; + +@end + +#endif /* __Random_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/RandomGenerating.h b/Headers/gnustep/base/RandomGenerating.h new file mode 100644 index 000000000..260282942 --- /dev/null +++ b/Headers/gnustep/base/RandomGenerating.h @@ -0,0 +1,39 @@ +/* Protocol for Objective-C objects that generate random bits + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RandomGenerating_h_INCLUDE_GNU +#define __RandomGenerating_h_INCLUDE_GNU + +#include + +@protocol RandomGenerating + ++ alloc; +- init; + +- (void) setRandomSeed: (long)seed; +- (long) nextRandom; + +@end + +#endif /* __RandomGenerating_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Retaining.h b/Headers/gnustep/base/Retaining.h new file mode 100644 index 000000000..70f1760e3 --- /dev/null +++ b/Headers/gnustep/base/Retaining.h @@ -0,0 +1,38 @@ +/* Protocol for GNU Objective-C objects that can keep a retain count. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Retaining_h_OBJECTS_INCLUDE +#define __Retaining_h_OBJECTS_INCLUDE + +#include + +@protocol Retaining + +- retain; +- (oneway void) release; +- (void) dealloc; +- (unsigned) retainCount; + +@end + +#endif /* __Retaining_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/RetainingNotifier.h b/Headers/gnustep/base/RetainingNotifier.h new file mode 100644 index 000000000..8cdc22bec --- /dev/null +++ b/Headers/gnustep/base/RetainingNotifier.h @@ -0,0 +1,57 @@ +/* Interface for reference-counted invalidation notifer object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Reference Counted object with invalidation notification + This object is just temporary. Eventually, we should separate + reference counting functionality from notification functionality */ + +#ifndef __RetainingNotifier_h +#define __RetainingNotifier_h + +#include +#include +#include +#include +#include + +@interface RetainingNotifier : Object +{ + Lock *refGate; + List *notificationList; + BOOL isValid; + int retain_count; +} + ++ initialize; +- init; +- free; +- (unsigned) retainCount; +- registerForInvalidationNotification: (id )anObject; +- unregisterForInvalidationNotification: (id )anObject; +- (BOOL) isValid; +- invalidate; +- copy; + +@end + +#endif /* __RetainingNotifier_h */ diff --git a/Headers/gnustep/base/Set.h b/Headers/gnustep/base/Set.h new file mode 100644 index 000000000..5e7278cb0 --- /dev/null +++ b/Headers/gnustep/base/Set.h @@ -0,0 +1,54 @@ +/* Interface for Objective-C Set collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Set_h_OBJECTS_INCLUDE +#define __Set_h_OBJECTS_INCLUDE + +#include +#include + +@interface Set : Collection +{ + coll_cache_ptr _contents_hash; // a hashtable to hold the contents; +} + +// MANAGING CAPACITY; ++ (unsigned) defaultCapacity; + +// INITIALIZING AND FREEING; +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; +- initWithCapacity: (unsigned)aCapacity; + +// SET OPERATIONS; +- intersectWithCollection: (id )aCollection; +- unionWithCollection: (id )aCollection; +- differenceWithCollection: (id )aCollection; + +- shallowCopyIntersectWithCollection: (id )aCollection; +- shallowCopyUnionWithCollection: (id )aCollection; +- shallowCopyDifferenceWithCollection: (id )aCollection; + +@end + +#endif /* __Set_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/SocketPort.h b/Headers/gnustep/base/SocketPort.h new file mode 100644 index 000000000..19e90d464 --- /dev/null +++ b/Headers/gnustep/base/SocketPort.h @@ -0,0 +1,57 @@ +/* Interface for socket-based port object for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SocketPort_h_INCLUDE_GNU +#define __SocketPort_h_INCLUDE_GNU + +#include +#include + +#include +#include +#include + +typedef struct sockaddr_in sockport_t; + +@interface SocketPort : Port +{ + sockport_t sockPort; + int sock; /* socket if local, 0 if remote */ + BOOL close_on_dealloc; +} + + ++ newForSockPort: (sockport_t)s close: (BOOL)f; ++ newForSockPort: (sockport_t)s; ++ newLocalWithNumber: (int)n; ++ newLocal; ++ newRemoteWithNumber: (int)n onHost: (const char*)h; + +- (sockport_t) sockPort; + +- (int) socket; +- (int) socketPortNumber; + +@end + +#endif /* __SocketPort_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/SplayTree.h b/Headers/gnustep/base/SplayTree.h new file mode 100644 index 000000000..73e3edfcf --- /dev/null +++ b/Headers/gnustep/base/SplayTree.h @@ -0,0 +1,48 @@ +/* Interface for Objective-C SplayTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Splay Tree. + Sleator and Tarjan. "Self-adjusting binary search trees." + Journal of the ACM, 32(3):652-686, 1985. + + includesObject:, minObject, maxObject, nextObject:, sortAddObject, + and removeObject: operations can all be done in O(lg n) amortized time. +*/ + + +#ifndef __SplayTree_h_INCLUDE_GNU +#define __SplayTree_h_INCLUDE_GNU + +#include +#include + +@interface SplayTree : BinaryTree +{ +} + +- splayNode: aNode; + +@end + +#endif /* __SplayTree_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/Stack.h b/Headers/gnustep/base/Stack.h new file mode 100644 index 000000000..bfd7d5d02 --- /dev/null +++ b/Headers/gnustep/base/Stack.h @@ -0,0 +1,47 @@ +/* Interface for Objective-C Stack object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Stack_h_INCLUDE_GNU +#define __Stack_h_INCLUDE_GNU + +#include +#include + +@interface Stack : Array + +- pushObject: anObject; +- popObject; +- topObject; +- duplicateTop; +- exchangeTop; + +// NON-OBJECT MESSAGE NAMES; +- pushElement: (elt)anElement; +- (elt) popElement; +- (elt) topElement; + + +@end + +#endif /* __Stack_h_INCLUDE_GNU */ + diff --git a/Headers/gnustep/base/StdioStream.h b/Headers/gnustep/base/StdioStream.h new file mode 100644 index 000000000..79e22f662 --- /dev/null +++ b/Headers/gnustep/base/StdioStream.h @@ -0,0 +1,50 @@ +/* Interface for GNU Objective C stdio stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __StdioStream_h__OBJECTS_INCLUDE +#define __StdioStream_h__OBJECTS_INCLUDE + +#include +#include +#include + +@interface StdioStream : Stream +{ + FILE *fp; +} + ++ standardIn; ++ standardOut; ++ standardError; + +- initWithFilePointer: (FILE*)afp fmode: (const char *)m; +- initWithFilename: (const char *)name fmode: (const char *)m; +- initWithFileDescriptor: (int)fd fmode: (const char *)m; + +- initWithPipeTo: (const char *)systemCommand; +- initWithPipeFrom: (const char *)systemCommand; + +@end + +#endif /* __StdioStream_h__OBJECTS_INCLUDE */ + diff --git a/Headers/gnustep/base/Stream.h b/Headers/gnustep/base/Stream.h new file mode 100644 index 000000000..590f777bf --- /dev/null +++ b/Headers/gnustep/base/Stream.h @@ -0,0 +1,67 @@ +/* Interface for GNU Objective C byte stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Stream_h__OBJECTS_INCLUDE +#define __Stream_h__OBJECTS_INCLUDE + +#include + +/* More modes needed? truncate? create? */ +enum +{ + STREAM_READONLY = 0, + STREAM_WRITEONLY, + STREAM_READWRITE +}; + +@interface Stream : Object +{ + int mode; +} + +- initWithMode: (int)m; +- init; + +- (int) writeByte: (unsigned char)b; +- (int) readByte: (unsigned char*)b; + +- (int) writeBytes: (const void*)b length: (int)l; +- (int) readBytes: (void*)b length: (int)l; + +- (int) writeFormat: (const char *)format, ...; +- (int) readFormat: (const char *)format, ...; + +- (void) writeLine: (const char *)l; +- (char *) readLine; + +- (void) rewindStream; +- (void) flushStream; +- (void) setStreamPosition: (unsigned)i; +- (unsigned) streamPosition; +- (BOOL) streamEof; +- (int) streamMode; + +@end + +#endif /* __Stream_h__OBJECTS_INCLUDE */ + diff --git a/Headers/gnustep/base/Time.h b/Headers/gnustep/base/Time.h new file mode 100644 index 000000000..496ef947f --- /dev/null +++ b/Headers/gnustep/base/Time.h @@ -0,0 +1,85 @@ +/* Interface for Objective-C Time object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is a combination of Smalltalk's Time and Date objects */ + +#ifndef __Time_h_OBJECTS_INCLUDE +#define __Time_h_OBJECTS_INCLUDE + +#include +#include +#include +#include + +@interface Time : Magnitude +{ + struct timeval tv; /* seconds and useconds */ + struct timezone tz; /* minutes from Greenwich, and correction */ +} + +/* Change these names? */ ++ (long) secondClockValue; ++ getClockValueSeconds: (long *)sec microseconds: (long *)usec; + ++ (long) millisecondsToRun: (void(*)())aFunc; ++ getSeconds: (long *)sec microseconds: (long *)usec toRun: (void(*)())aFunc; + ++ (unsigned) indexOfDayName: (const char *)dayName; ++ (const char *) nameOfDayIndex: (unsigned)dayIndex; ++ (unsigned) indexOfMonthName: (const char *)monthName; ++ (const char *) nameOfMonthIndex: (unsigned)monthIndex; ++ (unsigned) daysInMonthIndex: (unsigned)monthIndex forYear: (unsigned)year; ++ (unsigned) daysInYear: (unsigned)year; ++ (BOOL) leapYear: (unsigned)year; + +- initNow; +- initDayIndex: (unsigned)dayIndex + monthIndex: (unsigned)monthIndex + year: (unsigned)year; +- initSeconds: (long)numSeconds microseconds: (long)numMicroseconds; +- initSeconds: (long)numSeconds; + +- setSeconds: (long)numSeconds microseconds: (long)numMicroseconds; +- setSeconds: (long)numSeconds; + +- (long) days; +- (long) hours; +- (long) minutes; +- (long) seconds; +- (long) microseconds; + +- addTime: (Time*)aTimeObj; +- addDays: (unsigned)num; +- addHours: (unsigned)num; +- addMinutes: (unsigned)num; +- addSeconds: (unsigned)num; + +- subtractTime: (Time*)aTimeObj; +- subtractDays: (unsigned)num; +- subtractHours: (unsigned)num; +- subtractMinutes: (unsigned)num; +- subtractSeconds: (unsigned)num; + +@end + +#endif /* __Time_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/ValueHolding.h b/Headers/gnustep/base/ValueHolding.h new file mode 100644 index 000000000..da14b32f8 --- /dev/null +++ b/Headers/gnustep/base/ValueHolding.h @@ -0,0 +1,50 @@ +/* Protocol for Objective-C objects that hold numerical and/or string values. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ValueHolding_h_INCLUDE_GNU +#define __ValueHolding_h_INCLUDE_GNU + +#include + +@class String; + +@protocol ValueGetting +- (int) intValue; +- (float) floatValue; +- (double) doubleValue; +- (const char *) cStringValue; +- (String *) stringValue; +@end + +@protocol ValueSetting +- setIntValue: (int)anInt; +- setFloatValue: (float)aFloat; +- setDoubleValue: (double)aDouble; +- setCStringValue: (const char *)aCString; +- setStringValue: (String*)aString; +@end + +@protocol ValueHolding +@end + +#endif /* __ValueHolding_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/all.h b/Headers/gnustep/base/all.h new file mode 100644 index 000000000..8d0671981 --- /dev/null +++ b/Headers/gnustep/base/all.h @@ -0,0 +1,78 @@ +/* Includes interfaces for all concrete objects classes + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __objects_h_OBJECTS_INCLUDE +#define __objects_h_OBJECTS_INCLUDE + +#include + +/* Collection objects */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Magnitude objects */ +#include +#include +#include + +/* Stream objects */ +#include +#include +#include + +/* Coder objects */ +#include +#include +#include + +/* Port objects */ +#include +#include + +/* Remote messaging support objects */ +#include +#include +#include + +#endif /* __objects_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/config.h.in b/Headers/gnustep/base/config.h.in new file mode 100644 index 000000000..3710728a1 --- /dev/null +++ b/Headers/gnustep/base/config.h.in @@ -0,0 +1,30 @@ +/* Configuration information for the GNU Objective-C Library. + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: Oct 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __config_h_OBJECTS_INCLUDE +#define __config_h_OBJECTS_INCLUDE + +#define NeXT_runtime @NeXT_runtime@ +#define NeXT_cc @NeXT_cc@ + +#endif /* __config_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/mframe.h b/Headers/gnustep/base/mframe.h new file mode 100644 index 000000000..b08a2133e --- /dev/null +++ b/Headers/gnustep/base/mframe.h @@ -0,0 +1,43 @@ +/* Interface for functions that dissect/make method calls + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: Oct 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __mframe_h_OBJECTS_INCLUDE +#define __mframe_h_OBJECTS_INCLUDE + +#include + +BOOL +dissect_method_call(arglist_t frame, const char *type, + void (*f)(int,void*,const char*,int)); + +retval_t +dissect_method_return(arglist_t frame, const char *type, + BOOL out_parameters, + void(*f)(int,void*,const char*,int)); + +void +make_method_call(const char *forward_type, + void(*fd)(int,void*,const char*), + void(*fe)(int,void*,const char*,int)); + +#endif /* __mframe_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/objc-gnu2next.h b/Headers/gnustep/base/objc-gnu2next.h new file mode 100644 index 000000000..ee7664e4a --- /dev/null +++ b/Headers/gnustep/base/objc-gnu2next.h @@ -0,0 +1,235 @@ +/* Definitions to allow compilation of GNU objc code with NeXT runtime + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file is by no means complete. */ + +#ifndef __objc_gnu2next_h_INCLUDE_GNU +#define __objc_gnu2next_h_INCLUDE_GNU + +#include + +#if NeXT_runtime + +#define arglist_t marg_list +#define retval_t void* +#define TypedStream NXTypedStream + +#define objc_write_type(STREAM, TYPE, VAR) \ + NXWriteType(STREAM, TYPE, VAR) +#define objc_write_types(STREAM, TYPE, args...) \ + NXWriteTypes(STREAM, TYPE, args) +#define objc_write_object(STREAM, VAR) \ + NXWriteObject(STREAM, VAR) +#define objc_write_object_reference(STREAM, VAR) \ + NXWriteObjectReference(STREAM, VAR) +#define objc_read_type(STREAM, TYPE, VAR) \ + NXReadType(STREAM, TYPE, VAR) +#define objc_read_types(STREAM, TYPE, args...) \ + NXReadTypes(STREAM, TYPE, args) +#define objc_read_object(STREAM, VAR) \ + do { (*(VAR)) = NXReadObject(STREAM); } while (0) +#define objc_write_root_object \ + NXWriteRootObject +#define objc_open_typed_stream_for_file \ + NXOpenTypedStreamForFile +#define objc_close_typed_stream NXCloseTypedStream + +#define class_create_instance(CLASS) class_createInstance(CLASS, 0) +#define sel_get_name(ASEL) sel_getName(ASEL) +#define sel_get_uid(METHODNAME) set_getUid(METHODNAME) +#define class_get_instance_method(CLASSPOINTER, SEL) \ + class_getInstanceMethod(CLASSPOINTER, SEL) +#define class_get_class_method(CLASSPOINTER, SEL) \ + class_getClassMethod(CLASSPOINTER, SEL) +#define class_get_class_name(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->name) +#define method_get_sizeof_arguments(METHOD) \ + method_getSizeOfArguments(METHOD) +#define objc_lookup_class(CLASSNAME) \ + objc_lookUpClass(CLASSNAME) +#define sel_get_any_uid(SELNAME) \ + sel_getUid(SELNAME) +#define object_get_class(OBJECT) \ + (((struct objc_class*)(OBJECT))->isa) +#define class_get_super_class(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->super_class) +#define objc_get_class(CLASSNAME) \ + objc_lookUpClass(CLASSNAME) /* not exactly right */ +#define class_get_version(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->version) +#define __objc_responds_to(OBJECT,SEL) \ + class_getInstanceMethod(object_get_class(OBJECT), SEL) +#define CLS_ISMETA(CLASSPOINTER) \ + ((((struct objc_class*)(CLASSPOINTER))->info) & CLS_META) +#define objc_msg_lookup(OBJ,SEL) \ + (class_getInstanceMethod(object_get_class(OBJ), SEL)->method_imp) + +#if 1 +volatile void objc_fatal(const char* msg); +#else +#define objc_fatal(FMT, args...) \ + do { fprintf (stderr, (FMT), ##args); abort(); } while (0) +#endif + +#define OBJC_READONLY 1 +#define OBJC_WRITEONLY 2 + + +/* Methods defined by the GNU runtime, which libobjects will provide + if the GNU runtime isn't being used. */ + +int objc_sizeof_type(const char* type); +int objc_alignof_type(const char* type); +int objc_aligned_size (const char* type); +int objc_promoted_size (const char* type); +inline const char* objc_skip_type_qualifiers (const char* type); +const char* objc_skip_typespec (const char* type); +inline const char* objc_skip_offset (const char* type); +const char* objc_skip_argspec (const char* type); +unsigned objc_get_type_qualifiers (const char* type); + +/* The following from GNU's objc/list.h */ + +#include +#include + +struct objc_list { + void *head; + struct objc_list *tail; +}; + +/* Return a cons cell produced from (head . tail) */ + +static inline struct objc_list* +list_cons(void* head, struct objc_list* tail) +{ + struct objc_list* cell; + + cell = (struct objc_list*)(*objc_malloc)(sizeof(struct objc_list)); + cell->head = head; + cell->tail = tail; + return cell; +} + +/* Return the length of a list, list_length(NULL) returns zero */ + +static inline int +list_length(struct objc_list* list) +{ + int i = 0; + while(list) + { + i += 1; + list = list->tail; + } + return i; +} + +/* Return the Nth element of LIST, where N count from zero. If N + larger than the list length, NULL is returned */ + +static inline void* +list_nth(int index, struct objc_list* list) +{ + while(index-- != 0) + { + if(list->tail) + list = list->tail; + else + return 0; + } + return list->head; +} + +/* Remove the element at the head by replacing it by its successor */ + +static inline void +list_remove_head(struct objc_list** list) +{ + if ((*list)->tail) + { + struct objc_list* tail = (*list)->tail; /* fetch next */ + *(*list) = *tail;/* copy next to list head */ + (*objc_free)(tail);/* free next */ + } + else/* only one element in list */ + { + (*objc_free)(*list); + (*list) = 0; + } +} + + +/* Remove the element with `car' set to ELEMENT */ + +static inline void +list_remove_elem(struct objc_list** list, void* elem) +{ + while (*list) { + if ((*list)->head == elem) + list_remove_head(list); + list = &((*list)->tail); + } +} + +/* Map FUNCTION over all elements in LIST */ + +static inline void +list_mapcar(struct objc_list* list, void(*function)(void*)) +{ + while(list) + { + (*function)(list->head); + list = list->tail; + } +} + +/* Return element that has ELEM as car */ + +static inline struct objc_list** +list_find(struct objc_list** list, void* elem) +{ + while(*list) + { + if ((*list)->head == elem) + return list; + list = &((*list)->tail); + } + return NULL; +} + +/* Free list (backwards recursive) */ + +static void +list_free(struct objc_list* list) +{ + if(list) + { + list_free(list->tail); + (*objc_free)(list); + } +} + +#endif /* NeXT_runtime */ + +#endif /* __objc_gnu2next_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/objc-malloc.h b/Headers/gnustep/base/objc-malloc.h new file mode 100644 index 000000000..58fb5fd62 --- /dev/null +++ b/Headers/gnustep/base/objc-malloc.h @@ -0,0 +1,44 @@ +/* Memory allocation definitions for Objective-C, easy garbage collection. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __objc_malloc_h_INCLUDE_GNU +#define __objc_malloc_h_INCLUDE_GNU + +/* I do this to make substituting Boehm's Garbage Collection easy. */ +extern void *(*objc_malloc)(size_t); +extern void *(*objc_atomic_malloc)(size_t); +extern void *(*objc_realloc)(void *, size_t); +extern void *(*objc_calloc)(size_t, size_t); +extern void (*objc_free)(void *); + +#define OBJC_MALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_malloc)((unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_ATOMIC_MALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_atomic_malloc)((unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_REALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_realloc)((VAR), (unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_CALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_calloc)((unsigned)(NUM), sizeof(TYPE))) +#define OBJC_FREE(PTR) (*objc_free)((PTR)) + +#endif /* __objc_malloc_h_INCLUDE_GNU */ diff --git a/Headers/gnustep/base/objects.h b/Headers/gnustep/base/objects.h new file mode 100644 index 000000000..8d0671981 --- /dev/null +++ b/Headers/gnustep/base/objects.h @@ -0,0 +1,78 @@ +/* Includes interfaces for all concrete objects classes + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __objects_h_OBJECTS_INCLUDE +#define __objects_h_OBJECTS_INCLUDE + +#include + +/* Collection objects */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Magnitude objects */ +#include +#include +#include + +/* Stream objects */ +#include +#include +#include + +/* Coder objects */ +#include +#include +#include + +/* Port objects */ +#include +#include + +/* Remote messaging support objects */ +#include +#include +#include + +#endif /* __objects_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/preface.h.in b/Headers/gnustep/base/preface.h.in new file mode 100644 index 000000000..b58be37ca --- /dev/null +++ b/Headers/gnustep/base/preface.h.in @@ -0,0 +1,119 @@ +/* General purpose definitions for the GNU Objective-C Library. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __stdobjects_h_OBJECTS_INCLUDE +#define __stdobjects_h_OBJECTS_INCLUDE + +#include +#include +#include +#include + +#if NeXT_runtime + #include + #include + #include + #ifndef _C_ATOM + #define _C_ATOM '%' + #endif + #define _F_CONST 0x01 + #define _F_IN 0x01 + #define _F_OUT 0x02 + #define _F_INOUT 0x03 + #define _F_BYCOPY 0x04 + #define _F_ONEWAY 0x08 + #define _C_CONST 'r' + #define _C_IN 'n' + #define _C_INOUT 'N' + #define _C_OUT 'o' + #define _C_BYCOPY 'O' + #define _C_ONEWAY 'V' + #define CLASS Class +#else /* GNU Objective C Runtime */ + #include + #include + #include + #include + #include + #define CLASS Class* +#endif + +#include +#include + +/* The following two lines are maintained by the libobjects Makefile */ +#define OBJECTS_VERSION 0.1.0 +#define OBJECTS_GCC_VERSION 2.6.1 + +extern const char objects_version[]; +extern const char objects_gcc_version[]; +#if NeXT_cc +extern const char objects_NeXT_cc_version[]; +#endif + +#define LAMBDA(RETTYPE, ARGS, BODY) \ +({RETTYPE __lambda_func ARGS BODY __lambda_func;}) + +#define LAMBDA_VOID_PERFORM(SELECTOR) \ +LAMBDA(void, (id _o), {[_o perform: SELECTOR];}) + +#define LAMBDA_ID_PERFORM(SELECTOR) \ +LAMBDA(id, (id _o), {return [_o perform: SELECTOR];}) + +#define LAMBDA_BOOL_PERFORM(SELECTOR) \ +LAMBDA(BOOL, (id _o), {if ([_o perform:SELECTOR]) return YES; else return NO;}) + + +#ifndef MAX +#define MAX(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a > _b ? _a : _b; }) +#endif + +#ifndef MIN +#define MIN(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a < _b ? _a : _b; }) +#endif + +#ifndef PTR2LONG +#define PTR2LONG(P) (((char*)(P))-(char*)0) +#endif +#ifndef LONG2PTR +#define LONG2PTR(L) (((char*)0)+(L)) +#endif + +/* GNU Object.[hm] defines -compare:, NeXT doesn't, libobjects needs it. */ +#if NeXT_runtime +@interface Object (GNUExtensions) +- (int)compare:anotherObject; +- shouldNotImplement:(SEL)op; +@end +#endif /* NeXT_runtime */ + +#endif /* __stdobjects_h_OBJECTS_INCLUDE */ + + + diff --git a/Headers/gnustep/base/stdobjects.h.in b/Headers/gnustep/base/stdobjects.h.in new file mode 100644 index 000000000..b58be37ca --- /dev/null +++ b/Headers/gnustep/base/stdobjects.h.in @@ -0,0 +1,119 @@ +/* General purpose definitions for the GNU Objective-C Library. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __stdobjects_h_OBJECTS_INCLUDE +#define __stdobjects_h_OBJECTS_INCLUDE + +#include +#include +#include +#include + +#if NeXT_runtime + #include + #include + #include + #ifndef _C_ATOM + #define _C_ATOM '%' + #endif + #define _F_CONST 0x01 + #define _F_IN 0x01 + #define _F_OUT 0x02 + #define _F_INOUT 0x03 + #define _F_BYCOPY 0x04 + #define _F_ONEWAY 0x08 + #define _C_CONST 'r' + #define _C_IN 'n' + #define _C_INOUT 'N' + #define _C_OUT 'o' + #define _C_BYCOPY 'O' + #define _C_ONEWAY 'V' + #define CLASS Class +#else /* GNU Objective C Runtime */ + #include + #include + #include + #include + #include + #define CLASS Class* +#endif + +#include +#include + +/* The following two lines are maintained by the libobjects Makefile */ +#define OBJECTS_VERSION 0.1.0 +#define OBJECTS_GCC_VERSION 2.6.1 + +extern const char objects_version[]; +extern const char objects_gcc_version[]; +#if NeXT_cc +extern const char objects_NeXT_cc_version[]; +#endif + +#define LAMBDA(RETTYPE, ARGS, BODY) \ +({RETTYPE __lambda_func ARGS BODY __lambda_func;}) + +#define LAMBDA_VOID_PERFORM(SELECTOR) \ +LAMBDA(void, (id _o), {[_o perform: SELECTOR];}) + +#define LAMBDA_ID_PERFORM(SELECTOR) \ +LAMBDA(id, (id _o), {return [_o perform: SELECTOR];}) + +#define LAMBDA_BOOL_PERFORM(SELECTOR) \ +LAMBDA(BOOL, (id _o), {if ([_o perform:SELECTOR]) return YES; else return NO;}) + + +#ifndef MAX +#define MAX(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a > _b ? _a : _b; }) +#endif + +#ifndef MIN +#define MIN(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a < _b ? _a : _b; }) +#endif + +#ifndef PTR2LONG +#define PTR2LONG(P) (((char*)(P))-(char*)0) +#endif +#ifndef LONG2PTR +#define LONG2PTR(L) (((char*)0)+(L)) +#endif + +/* GNU Object.[hm] defines -compare:, NeXT doesn't, libobjects needs it. */ +#if NeXT_runtime +@interface Object (GNUExtensions) +- (int)compare:anotherObject; +- shouldNotImplement:(SEL)op; +@end +#endif /* NeXT_runtime */ + +#endif /* __stdobjects_h_OBJECTS_INCLUDE */ + + + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..a448f39f7 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,397 @@ +# @configure_input@ +# +# Main makefile for GNU Objective-C Class library +# Copyright (C) 1993,1994 Free Software Foundation, Inc. +# +# Written by: R. Andrew McCallum +# Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 +# +# This file is part of the GNU Objective-C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +SHELL = /bin/sh + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +RANLIB = @RANLIB@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +AR = ar +ARFLAGS = rc +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +LEX = flex +LFLAGS = + +DEFS = @DEFS@ + +# All these are optional. You can redifine CFLAGS, CPPFLAGS and +# INCLUDEFLAGS on the command line however you like. +CFLAGS = -Wall -Wno-implicit -g +CPPFLAGS = +INCLUDEFLAGS = + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +# Installation locations +libdir = $(exec_prefix)/lib +includedir = $(prefix)/include/objects +infodir = $(prefix)/info + +#### End of system configuration section. #### + +# The gcc version required to compile the library. +OBJECTS_GCC_VERSION = 2.6.1 + +# The version number of this release. +OBJECTS_VERSION = 0.1.0 + +NEXT_NEXT_INCLUDES = -I/usr/include +OBJECTS_NEXT_INCLUDES = -I$(srcdir)/objects/next-include +NEXT_INCLUDES = @NEXT_INCLUDES@ + +ALL_INCLUDE_FLAGS = -I$(srcdir) $(NEXT_INCLUDES) $(INCLUDEFLAGS) +ALL_CPPFLAGS = $(ALL_INCLUDE_FLAGS) $(CPPFLAGS) +ALL_CFLAGS = $(CFLAGS) +ALL_OBJCFLAGS = $(CFLAGS) -Wno-protocol + +# definitions to be passed to subdir Makefile's +MAKEDEFINES = CC='$(CC)' CFLAGS='$(CFLAGS)' CPPFLAGS='$(CPPFLAGS)' \ +INCLUDEFLAGS='$(INCLUDEFLAGS)' DEFS='$(DEFS)' + +.SUFFIXES: .m +.m.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) $< +.c.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_CFLAGS) $< + +GNU_MFILES = \ +Array.m \ +Bag.m \ +BinaryCoder.m \ +BinaryTree.m \ +BinaryTreeEltNode.m \ +BinaryTreeNode.m \ +CircularArray.m \ +Coder.m \ +Collection.m \ +ConnectedCoder.m \ +Connection.m \ +DelegatePool.m \ +Dictionary.m \ +EltNodeCollector.m \ +GapArray.m \ +Heap.m \ +IndexedCollection.m \ +KeyedCollection.m \ +LinkedList.m \ +LinkedListEltNode.m \ +LinkedListNode.m \ +Lock.m \ +Magnitude.m \ +MappedCollector.m \ +MemoryStream.m \ +Port.m \ +Proxy.m \ +Queue.m \ +Random.m \ +RBTree.m \ +RBTreeEltNode.m \ +RBTreeNode.m \ +RNGAdditiveCongruential.m \ +RNGBerkeley.m \ +RetainingNotifier.m \ +Set.m \ +SocketPort.m \ +SplayTree.m \ +Stack.m \ +StdioStream.m \ +Stream.m \ +TextCoder.m \ +Time.m \ +stdobjects.m \ +mframe.m \ +objc-gnu2next.m \ +eltfuncs.m + +NeXT_MFILES = \ +HashTable.m \ +List.m \ +NXStringTable.m \ +Storage.m + +GNU_CFILES = \ +collhash.c \ +objc-malloc.c \ +o_vscanf.c + +NeXT_CFILES = \ +NXStringTable_scan.c \ +zone.c + +GNU_OTHER_SRCFILES = + +NeXT_OTHER_SRCFILES = \ +NXStringTable_scan.l + +GNU_OBJS = $(GNU_MFILES:.m=.o) $(GNU_CFILES:.c=.o) +NeXT_OBJS = $(NeXT_MFILES:.m=.o) $(NeXT_CFILES:.c=.o) + +GNU_HEADERS = \ +objects/Array.h \ +objects/ArrayPrivate.h \ +objects/Bag.h \ +objects/BinaryCoder.h \ +objects/BinaryTree.h \ +objects/BinaryTreeEltNode.h \ +objects/BinaryTreeNode.h \ +objects/CircularArray.h \ +objects/CircularArrayPrivate.h \ +objects/Coder.h \ +objects/Coding.h \ +objects/Collecting.h \ +objects/Collection.h \ +objects/CollectionPrivate.h \ +objects/ConnectedCoder.h \ +objects/Connection.h \ +objects/DelegatePool.h \ +objects/Dictionary.h \ +objects/EltNodeCollector.h \ +objects/EltNode-h \ +objects/EltNode-m \ +objects/GapArray.h \ +objects/GapArrayPrivate.h \ +objects/Heap.h \ +objects/IndexedCollecting.h \ +objects/IndexedCollection.h \ +objects/IndexedCollectionPrivate.h \ +objects/InvalidationListening.h \ +objects/KeyedCollecting.h \ +objects/KeyedCollection.h \ +objects/LinkedList.h \ +objects/LinkedListEltNode.h \ +objects/LinkedListNode.h \ +objects/Lock.h \ +objects/Locking.h \ +objects/Magnitude.h \ +objects/MappedCollector.h \ +objects/MemoryStream.h \ +objects/Ordering.h \ +objects/Port.h \ +objects/Proxy.h \ +objects/Queue.h \ +objects/RBTree.h \ +objects/RBTreeEltNode.h \ +objects/RBTreeNode.h \ +objects/RNGAdditiveCongruential.h \ +objects/RNGBerkeley.h \ +objects/Random.h \ +objects/RandomGenerating.h \ +objects/Retaining.h \ +objects/RetainingNotifier.h \ +objects/Set.h \ +objects/SocketPort.h \ +objects/SplayTree.h \ +objects/Stack.h \ +objects/StdioStream.h \ +objects/Stream.h \ +objects/TextCoder.h \ +objects/Time.h \ +objects/ValueHolding.h \ +objects/collhash.h \ +objects/config.h \ +objects/elt.h \ +objects/eltfuncs.h \ +objects/mframe.h \ +objects/objc-gnu2next.h \ +objects/objc-malloc.h \ +objects/objects.h \ +objects/stdobjects.h + +NeXT_HEADERS = \ +objects/next-include/objc/HashTable.h \ +objects/next-include/objc/List.h \ +objects/next-include/objc/NXStringTable.h \ +objects/next-include/objc/Storage.h \ +objects/next-include/objc/zone.h + +INSTALL_HEADERS = @INSTALL_HEADERS@ +INSTALL_OBJS = @INSTALL_OBJS@ + +DIST_FILES = \ +README readme.texi \ +ANNOUNCE announce.texi \ +INSTALL install.texi \ +TODO todo.texi \ +NEWS news.texi \ +CREDITS \ +COPYING COPYING.LIB DISCUSSION ChangeLog \ +Makefile.in configure configure.in objects/config.h.in \ +config.guess config.nested.c config.nextcc.h config.nextrt.m \ +mkinstalldirs install-sh \ +version.texi \ +libobjects.info libobjects.texi \ +texinfo.tex \ +$(GNU_MFILES) $(NeXT_MFILES) \ +$(GNU_CFILES) $(NeXT_CFILES) \ +$(GNU_HEADERS) $(NeXT_HEADERS) \ +$(GNU_OTHER_SRCFILES) $(NeXT_OTHER_SRCFILES) + +all: libobjects.a + +libobjects.a: $(INSTALL_OBJS) + $(AR) $(ARFLAGS) libobjects.a $(INSTALL_OBJS) + $(RANLIB) libobjects.a + +install: installdirs all + $(INSTALL_DATA) libobjects.a $(libdir)/libobjects.a + $(RANLIB) $(libdir)/libobjects.a + for file in $(INSTALL_HEADERS); do \ + $(INSTALL_DATA) $$file $(includedir) ; \ + done + $(INSTALL_DATA) libobjects.info $(infodir) + +installdirs: + $(srcdir)/mkinstalldirs $(libdir) $(infodir) \ + $(includedir) \ + $(includedir)/next-include \ + $(includedir)/next-include/objc \ + $(includedir)/next-include/foundation + +uninstall: + rm -f $(libdir)/libobjects.a + rm -rf $(includedir) + rm -f $(infodir)/libobjects.info + +check: libobjects.a + cd checks; $(MAKE) -$(MAKEFLAGS) $(MAKEDEFINES) + +depend: + rm -f $(srcdir)/Makefile.depend + $(CC) $(ALL_INCLUDE_FLAGS) -M $(SRCS) > $(srcdir)/Makefile.depend + +NXStringTable_scan.c: NXStringTable_scan.l + $(LEX) $(LFLAGS) -t NXStringTable_scan.l > NXStringTable_scan.temp + sed 's/yy/NXlex_/g' < NXStringTable_scan.temp > NXStringTable_scan.c + $(RM) -f NXStringTable_scan.temp + +# remove this special case? +# turn off warnings while compiling NXStringTable_scan.c +NXStringTable_scan.o: NXStringTable_scan.c + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_CFLAGS) -w NXStringTable_scan.c + +objects/stdobjects.h: Makefile.in + rm -f tmp-stdobjects.h + sed -e \ + 's/#define OBJECTS_VERSION .*/#define OBJECTS_VERSION $(OBJECTS_VERSION)/'\ + < objects/stdobjects.h >tmp-stdobjects.h + rm $(srcdir)/objects/stdobjects.h + sed -e \ + 's/#define OBJECTS_GCC_VERSION .*/#define OBJECTS_GCC_VERSION $(OBJECTS_GCC_VERSION)/'\ + < tmp-stdobjects.h > $(srcdir)/objects/stdobjects.h + +stdobjects.m: objects/stdobjects.h + +version.texi: Makefile + rm -f $(srcdir)/version.texi + echo '@set OBJECTS_VERSION' $(OBJECTS_VERSION) > $(srcdir)/version.texi + echo '@set OBJECTS_GCC_VERSION' $(OBJECTS_GCC_VERSION) \ + >> $(srcdir)/version.texi + +info: libobjects.info TODO INSTALL NEWS README ANNOUNCE +dvi: libobjects.texi version.texi + $(TEXI2DVI) $(srcdir)/libobjects.texi + +libobjects.info: libobjects.texi todo.texi version.texi + $(MAKEINFO) $(srcdir)/libobjects.texi +TODO: todo.texi version.texi + $(MAKEINFO) -o TODO -D TODO_ONLY \ + --no-header --no-split $(srcdir)/todo.texi +INSTALL: install.texi version.texi + $(MAKEINFO) -o INSTALL -D INSTALL_ONLY \ + --no-header --no-split $(srcdir)/install.texi +README: readme.texi version.texi + $(MAKEINFO) -o README -D README_ONLY \ + --no-header --no-split $(srcdir)/readme.texi +ANNOUNCE: announce.texi version.texi + $(MAKEINFO) -o ANNOUNCE -D ANNOUNCE_ONLY \ + --no-header --no-split $(srcdir)/announce.texi +NEWS: news.texi version.texi + $(MAKEINFO) -o NEWS -D NEWS_ONLY \ + --no-header --no-split $(srcdir)/news.texi +Makefile: Makefile.in config.status + $(SHELL) config.status +config.status: configure + $(SHELL) $(srcdir)/configure --no-create +configure: configure.in + cd $(srcdir); autoconf + +TAGS: $(SRCS) + etags $(SRCS) + +mostlyclean: + rm -f core \ + *~ \ + objects/*~ \ + objects/next-include/*~ \ + objects/next-include/foundation/*~ \ + objects/next-include/objc/*~ + +clean: mostlyclean + rm -f libobjects.a *.o + rm -f libobjects.dvi libobjects.aux libobjects.log \ + libobjects.toc libobjects.cl \ + libobjects.cp libobjects.cps libobjects.fn libobjects.fns \ + libobjects.ky libobjects.pg libobjects.pr libobjects.tp \ + libobjects.vr + +distclean: clean + rm -f Makefile config.status config.log config.cache + +realclean: distclean + rm -f TAGS configure \ + libobjects.info version.texi README TODO INSTALL NEWS ANNOUNCE + +dist: $(DIST_FILES) + echo libobjects-$(OBJECTS_VERSION) > .fname + rm -rf `cat .fname` + mkdir `cat .fname` + mkdir `cat .fname`/objects + mkdir `cat .fname`/objects/next-include + mkdir `cat .fname`/objects/next-include/objc + mkdir `cat .fname`/objects/next-include/foundation + # previously did this: -ln (DIST_FILES) `cat .fname` + for file in $(DIST_FILES); do \ + ln $$file `cat .fname`/$$file ; \ + done + touch `cat .fname`/Makefile.local + touch `cat .fname`/Makefile.depend + cd checks; $(MAKE) $(MAKEFLAGS) dist + cd examples; $(MAKE) $(MAKEFLAGS) dist + tar -chvf `cat .fname`.tar `cat .fname` + gzip `cat .fname`.tar + rm -rf `cat .fname` .fname + +include Makefile.depend + +include Makefile.local diff --git a/Source/Array.m b/Source/Array.m new file mode 100644 index 000000000..41b67b3de --- /dev/null +++ b/Source/Array.m @@ -0,0 +1,301 @@ +/* Implementation for Objective-C Array collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation Array + ++ initialize +{ + if (self == [Array class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// MANAGING CAPACITY; + +/* Eventually we will want to have better capacity management, + potentially keep default capacity as a class variable. */ + ++ (unsigned) defaultCapacity +{ + return DEFAULT_ARRAY_CAPACITY; +} + ++ (unsigned) defaultGrowFactor +{ + return DEFAULT_ARRAY_GROW_FACTOR; +} + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity +{ + [super initWithType:contentEncoding]; + _comparison_function = elt_get_comparison_function(contentEncoding); + _grow_factor = [[self class] defaultGrowFactor]; + _count = 0; + _capacity = (aCapacity < 1) ? 1 : aCapacity; + OBJC_MALLOC(_contents_array, elt, _capacity); + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) _encodeCollectioinWitCoder: (Coder*)coder +{ + const char *encoding = [self contentType]; + + [super encodeWithCoder:coder]; + [coder encodeValueOfSimpleType:@encode(char*) + at:&encoding + withName:"Array Encoding Type"]; + [coder encodeValueOfSimpleType:@encode(unsigned) + at:&_grow_factor + withName:"Array Grow Factor"]; + [coder encodeValueOfSimpleType:@encode(unsigned) + at:&_capacity + withName:"Array Capacity"]; +} + ++ _newCollectionWithCoder: (Coder*)coder +{ + char *encoding; + Array *n = [super newWithCoder:coder]; + [coder decodeValueOfSimpleType:@encode(char*) + at:&encoding + withName:NULL]; + n->_comparison_function = elt_get_comparison_function(encoding); + [coder decodeValueOfSimpleType:@encode(unsigned) + at:&(n->_grow_factor) + withName:NULL]; + n->_count = 0; + [coder decodeValueOfSimpleType:@encode(unsigned) + at:&(n->_capacity) + withName:NULL]; + OBJC_MALLOC(n->_contents_array, elt, n->_capacity); + return n; +} + +- _writeInit: (TypedStream*)aStream +{ + const char *encoding = [self contentType]; + + [super _writeInit: aStream]; + // This implicitly archives the _comparison_function; + objc_write_type(aStream, @encode(char*), &encoding); + objc_write_type(aStream, @encode(unsigned int), &_grow_factor); + objc_write_type(aStream, @encode(unsigned int), &_capacity); + return self; +} + +- _readInit: (TypedStream*)aStream +{ + char *encoding; + + [super _readInit: aStream]; + objc_read_type(aStream, @encode(char*), &encoding); + _comparison_function = elt_get_comparison_function(encoding); + objc_read_type(aStream, @encode(unsigned int), &_grow_factor); + _count = 0; + objc_read_type(aStream, @encode(unsigned int), &_capacity); + OBJC_MALLOC(_contents_array, elt, _capacity); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + Array *copy = [super emptyCopy]; + copy->_count = 0; + OBJC_MALLOC(copy->_contents_array, elt, copy->_capacity); + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + _count = 0; + return self; +} + +- free +{ + OBJC_FREE(_contents_array); + return [super free]; +} + +- freeObjects +{ + if (CONTAINS_OBJECTS) + { + [self makeObjectsPerform:@selector(free)]; + [self empty]; + } + else + [self empty]; + return self; +} + +- initWithContentsOf: (id )aCollection +{ + [self initWithType:[aCollection contentType] + capacity:[aCollection count]]; + [self addContentsOf:aCollection]; + return self; +} + +- initWithCapacity: (unsigned)aCapacity +{ + return [self initWithType:@encode(id) capacity:aCapacity]; +} + +/* Catch designated initializer for IndexedCollection */ +- initWithType: (const char *)contentEncoding +{ + return [self initWithType:contentEncoding + capacity:[[self class] defaultCapacity]]; +} + +// MANAGING CAPACITY; + +/* This is the only method that changes the value of the instance + variable _capacity, except for "-initDescription:capacity:" */ + +- setCapacity: (unsigned)newCapacity +{ + if (newCapacity > _count) { + _capacity = newCapacity; + OBJC_REALLOC(_contents_array, elt, _capacity); + } + return self; +} + +- (unsigned) growFactor +{ + return _grow_factor; +} + +- setGrowFactor: (unsigned)aNum; +{ + _grow_factor = aNum; + return self; +} + +// ADDING; + +- appendElement: (elt)newElement +{ + incrementCount(self); + _contents_array[_count-1] = newElement; + return self; +} + +- prependElement: (elt)newElement +{ + incrementCount(self); + makeHoleAt(self, 0); + _contents_array[0] = newElement; + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count+1); + incrementCount(self); + makeHoleAt(self, index); + _contents_array[index] = newElement; + return self; +} + + +// REMOVING, REPLACING AND SWAPPING; + +- (elt) removeElementAtIndex: (unsigned)index +{ + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, _count); + ret = _contents_array[index]; + fillHoleAt(self, index); + decrementCount(self); + return ret; +} + +/* We could be more efficient if we override these also. + - (elt) removeFirstElement + - (elt) removeLastElement; */ + + +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement +{ + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, _count); + ret = _contents_array[index]; + _contents_array[index] = newElement; + return ret; +} + +- swapAtIndeces: (unsigned)index1 : (unsigned)index2 +{ + elt tmp; + + CHECK_INDEX_RANGE_ERROR(index1, _count); + CHECK_INDEX_RANGE_ERROR(index2, _count); + tmp = _contents_array[index1]; + _contents_array[index1] = _contents_array[index2]; + _contents_array[index2] = tmp; + return self; +} + + +// GETTING ELEMENTS BY INDEX; + +- (elt) elementAtIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count); + return _contents_array[index]; +} + +// TESTING; + +- (int(*)(elt,elt)) comparisonFunction +{ + return _comparison_function; +} + +- (const char *) contentType +{ + return elt_get_encoding(_comparison_function); +} + +- (unsigned) count +{ + return _count; +} + +@end + + diff --git a/Source/Bag.m b/Source/Bag.m new file mode 100644 index 000000000..79d8bdeed --- /dev/null +++ b/Source/Bag.m @@ -0,0 +1,302 @@ +/* Implementation for Objective-C Bag collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation Bag + ++ initialize +{ + if (self == [Bag class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// INITIALIZING AND FREEING; + +/* This is the designated initializer of this class */ +/* Override designated initializer of superclass */ +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity +{ + [super initWithType:contentEncoding + capacity:aCapacity]; + _count = 0; + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- _readInit: (TypedStream*)aStream +{ + [super _readInit:aStream]; + _count = 0; + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + Bag *copy = [super emptyCopy]; + copy->_count = 0; + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + coll_hash_empty(_contents_hash); + _count = 0; + return self; +} + +- freeObjects +{ + if (CONTAINS_OBJECTS) + { + [self makeObjectsPerform:@selector(free)]; + [self empty]; + } + else + [self empty]; + return self; +} + +// ADDING; + +- addElement: (elt)newElement withOccurrences: (unsigned)count +{ + coll_node_ptr node = + coll_hash_node_for_key(_contents_hash, newElement); + if (node) + node->value.unsigned_int_u += count; + else + coll_hash_add(&_contents_hash, newElement, count); + _count += count; + return self; +} + +- addElement: (elt)newElement +{ + return [self addElement:newElement withOccurrences:1]; +} + + +// REMOVING AND REPLACING; + +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(oldElement); + } + return [self removeElement:oldElement occurrences:count + ifAbsentCall:err]; +} + +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count + ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + coll_node_ptr node = + coll_hash_node_for_key(_contents_hash, oldElement); + if (!node || node->value.unsigned_int_u < count) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + if (node->value.unsigned_int_u > count) + { + (node->value.unsigned_int_u) -= count; + } + else /* (node->value.unsigned_int_u == count) */ + { + coll_hash_remove(_contents_hash, oldElement); + } + _count -= count; + return oldElement; +} + +- (elt) removeElement: (elt)oldElement ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + return [self removeElement:oldElement occurrences:1 ifAbsentCall:excFunc]; +} + +- uniqueContents +{ + void *state = 0; + coll_node_ptr node = 0; + + _count = 0; + while ((node = coll_hash_next(_contents_hash, &state))) + { + node->value.unsigned_int_u = 1; + _count++; + } + return self; +} + + +// TESTING; + +- (unsigned) count +{ + return _count; +} + +- (unsigned) uniqueCount +{ + return _contents_hash->used; +} + +- (unsigned) occurrencesOfElement: (elt)anElement +{ + coll_node_ptr node = + coll_hash_node_for_key(_contents_hash, anElement); + + if (node) + return node->value.unsigned_int_u; + else + return 0; +} + + +// ENUMERATING; + +struct BagEnumState +{ + void *state; + coll_node_ptr node; + unsigned count; +}; + +#define ES ((struct BagEnumState *) *enumState) + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + if (!(*enumState)) + { + } + else if (ES->count >= ES->node->value.unsigned_int_u) + { + /* time to get the next different element */ + ES->node = coll_hash_next(_contents_hash, &(ES->state)); + ES->count = 0; + } + if (!(ES->node)) + { + /* at end of enumeration */ + OBJC_FREE(*enumState); + *enumState = 0; + return NO; + } + *anElementPtr = ES->node->key; + (ES->count)++; + return YES; +} + +- (void*) newEnumState +{ + /* init for start of enumeration. */ + void *vp; + void **enumState = &vp; + OBJC_MALLOC(*enumState, struct BagEnumState, 1); + ES->state = 0; + ES->node = coll_hash_next(_contents_hash, &(ES->state)); + ES->count = 0; + return vp; +} + +- freeEnumState: (void**)enumState +{ + if (*enumState) + OBJC_FREE(*enumState); + return self; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + int i; + void *state = 0; + coll_node_ptr node; + + while ((node = coll_hash_next(_contents_hash, &state))) + { + for (i = 0; i < node->value.unsigned_int_u; i++) + { + if (!(*flag)) + return self; + (*aFunc)(node->key); + } + } + return self; +} + +- withElementsCall: (void(*)(elt))aFunc +{ + int i; + void *state = 0; + coll_node_ptr node; + int test = 0; + + while ((node = coll_hash_next(_contents_hash, &state))) + { + test++; + for (i = 0; i < node->value.unsigned_int_u; i++) + { + (*aFunc)(node->key); + } + } + return self; +} + + +// OBJECT-COMPATIBLE MESSAGE NAMES; + +- addObject: newObject withOccurrences: (unsigned)count +{ + return [self addElement:newObject withOccurrences:count]; +} + +- removeObject: oldObject occurrences: (unsigned)count +{ + id err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(oldObject); + } + return [self removeObject:oldObject occurrences:count ifAbsentCall:err]; +} + +- removeObject: oldObject occurrences: (unsigned)count + ifAbsentCall: (id(*)(arglist_t))excFunc +{ + elt elt_exc(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + return [self removeElement:oldObject occurrences:count + ifAbsentCall:elt_exc].id_u; +} + +@end + + diff --git a/Source/BinaryCoder.m b/Source/BinaryCoder.m new file mode 100644 index 000000000..bd9dde89d --- /dev/null +++ b/Source/BinaryCoder.m @@ -0,0 +1,329 @@ +/* Implementation of GNU Objective-C binary coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#define CONCRETE_FORMAT_VERSION 0 + +static BOOL debug_binary_coder = NO; + +@implementation BinaryCoder + ++ setDebugging: (BOOL)f +{ + debug_binary_coder = f; + return self; +} + ++ (TextCoder*) debugStderrCoder +{ + static TextCoder* c = nil; + + if (!c) + c = [[TextCoder alloc] initEncodingOnStream:[StdioStream standardError]]; + return c; +} + ++ (int) coderConcreteFormatVersion +{ + return CONCRETE_FORMAT_VERSION; +} + +/* Careful, this shouldn't contain newlines */ ++ (const char *) coderSignature +{ + return "GNU Objective C Class Library BinaryCoder"; +} + +- doInitOnStream: (Stream *)s isDecoding: (BOOL)f +{ + [super doInitOnStream:s isDecoding:f]; + return self; +} + +- (void) encodeValueOfSimpleType: (const char*)type + at: (const void*)d + withName: (const char *)name +{ + unsigned char size; + + if (debug_binary_coder) + { + [[BinaryCoder debugStderrCoder] + encodeValueOfSimpleType:type + at:d + withName:name]; + } + assert(type); + assert(*type != '@'); + assert(*type != '^'); + assert(*type != ':'); + assert(*type != '{'); + assert(*type != '['); + + /* A fairly stupid, inefficient binary encoding. This could use + some improvement. For instance, we could compress the sign + information and the type information. + It could probably also use some portability fixes. */ + [stream writeByte:*type]; + size = objc_sizeof_type(type); + [stream writeByte:size]; + switch (*type) + { + case _C_CHARPTR: + { + int length = strlen(*(char**)d); + [self encodeValueOfSimpleType:@encode(int) + at:&length withName:"BinaryCoder char* length"]; + [stream writeBytes:*(char**)d length:length]; + break; + } + + case _C_CHR: + if (*(char*)d < 0) + [stream writeByte:1]; + else + [stream writeByte:0]; + case _C_UCHR: + [stream writeByte:*(unsigned char*)d]; + break; + + case _C_SHT: + if (*(short*)d < 0) + [stream writeByte:1]; + else + [stream writeByte:0]; + case _C_USHT: + { + unsigned char *buf = alloca(size); + short s = *(short*)d; + int count = size; + if (s < 0) s = -s; + for (; count--; s >>= 8) + buf[count] = (char) (s % 0x100); + [stream writeBytes:buf length:size]; + break; + } + + case _C_INT: + if (*(int*)d < 0) + [stream writeByte:1]; + else + [stream writeByte:0]; + case _C_UINT: + { + unsigned char *buf = alloca(size); + int s = *(int*)d; + int count = size; + if (s < 0) s = -s; + for (; count--; s >>= 8) + buf[count] = (char) (s % 0x100); + [stream writeBytes:buf length:size]; + break; + } + + case _C_LNG: + if (*(long*)d < 0) + [stream writeByte:1]; + else + [stream writeByte:0]; + case _C_ULNG: + { + unsigned char *buf = alloca(size); + long s = *(long*)d; + int count = size; + if (s < 0) s = -s; + for (; count--; s >>= 8) + buf[count] = (char) (s % 0x100); + [stream writeBytes:buf length:size]; + break; + } + + /* Two quickie kludges to make archiving of floats and doubles work */ + case _C_FLT: + { + char buf[64]; + char *s = buf; + sprintf(buf, "%f", *(float*)d); + [self encodeValueOfSimpleType:@encode(char*) + at:&s withName:"BinaryCoder float"]; + break; + } + case _C_DBL: + { + char buf[64]; + char *s = buf; + sprintf(buf, "%f", *(double*)d); + [self encodeValueOfSimpleType:@encode(char*) + at:&s withName:"BinaryCoder double"]; + break; + } + default: + [self error:"Unrecognized Type %s", type]; + } +} + +- (void) decodeValueOfSimpleType: (const char*)type + at: (void*)d + withName: (const char **)namePtr +{ + char encoded_type; + unsigned char encoded_size; + unsigned char encoded_sign = 0; + + assert(type); + assert(*type != '@'); + assert(*type != '^'); + assert(*type != ':'); + assert(*type != '{'); + assert(*type != '['); + + [stream readByte:&encoded_type]; + if (encoded_type != *type + && !((encoded_type=='c' || encoded_type=='C') + && (*type=='c' || *type=='C'))) + [self error:"Expected type \"%c\", got type \"%c\"", *type, encoded_type]; + [stream readByte:&encoded_size]; + switch (encoded_type) + { + case _C_CHARPTR: + { + int length; + [self decodeValueOfSimpleType:@encode(int) + at:&length withName:NULL]; + OBJC_MALLOC(*(char**)d, char, length+1); + [stream readBytes:*(char**)d length:length]; + (*(char**)d)[length] = '\0'; + break; + } + + case _C_CHR: + [stream readByte:&encoded_sign]; + case _C_UCHR: + [stream readByte:(unsigned char*)d]; + if (encoded_sign) + *(char*)d = *(char*)d * -1; + break; + + case _C_SHT: + [stream readByte:&encoded_sign]; + case _C_USHT: + { + unsigned char *buf = alloca(encoded_size); + int i; + short s = 0; + [stream readBytes:buf length:encoded_size]; + for (i = 0; i < sizeof(short); i++) + { + s <<= 8; + s += buf[i]; + } + if (encoded_sign) + s = -s; + *(short*)d = s; + break; + } + + case _C_INT: + [stream readByte:&encoded_sign]; + case _C_UINT: + { + unsigned char *buf = alloca(encoded_size); + int i; + int s = 0; + [stream readBytes:buf length:encoded_size]; + for (i = 0; i < sizeof(int); i++) + { + s <<= 8; + s += buf[i]; + } + if (encoded_sign) + s = -s; + *(int*)d = s; + break; + } + + case _C_LNG: + [stream readByte:&encoded_sign]; + case _C_ULNG: + { + unsigned char *buf = alloca(encoded_size); + int i; + long s = 0; + [stream readBytes:buf length:encoded_size]; + for (i = 0; i < sizeof(long); i++) + { + s <<= 8; + s += buf[i]; + } + if (encoded_sign) + s = -s; + *(long*)d = s; + break; + } + + /* Two quickie kludges to make archiving of floats and doubles work */ + case _C_FLT: + { + char *buf; + [self decodeValueOfSimpleType:@encode(char*) at:&buf withName:NULL]; + if (sscanf(buf, "%f", (float*)d) != 1) + [self error:"expected float, got %s", buf]; + (*objc_free)(buf); + break; + } + case _C_DBL: + { + char *buf; + [self decodeValueOfSimpleType:@encode(char*) at:&buf withName:NULL]; + if (sscanf(buf, "%lf", (double*)d) != 1) + [self error:"expected double, got %s", buf]; + (*objc_free)(buf); + break; + } + default: + [self error:"Unrecognized Type %s", type]; + } + + if (debug_binary_coder) + { + [[BinaryCoder debugStderrCoder] + encodeValueOfSimpleType:type + at:d + withName:"decoding unnamed"]; + } +} + +- (void) encodeName: (const char *)name +{ + if (debug_binary_coder) + [[BinaryCoder debugStderrCoder] + encodeName:name]; +} + +@end diff --git a/Source/BinaryTree.m b/Source/BinaryTree.m new file mode 100644 index 000000000..5dd0e1861 --- /dev/null +++ b/Source/BinaryTree.m @@ -0,0 +1,616 @@ +/* Implementation for Objective-C BinaryTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +// do safety checks; +#define SAFE_BinaryTree 1 + +/* sentinal */ +static id nilBinaryTreeNode; + +@implementation BinaryTree + ++ initialize +{ + if (self == [BinaryTree class]) + { + [self setVersion:0]; /* beta release */ + nilBinaryTreeNode = [[BinaryTreeNode alloc] init]; + } + return self; +} + +/* This is the designated initializer of this class */ +- init +{ + [super initWithType:@encode(id)]; + _count = 0; + _contents_root = [self nilNode]; + return self; +} + +/* Archiving must mimic the above designated initializer */ + ++ _newCollectionWithCoder: (Coder*)aCoder +{ + BinaryTree *n; + n = [super _newCollectionWithCoder:aCoder]; + n->_count = 0; + n->_contents_root = [self nilNode]; + return n; +} + +- (void) _encodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder startEncodingInterconnectedObjects]; + [super _encodeContentsWithCoder:aCoder]; + [aCoder finishEncodingInterconnectedObjects]; +} + +- (void) _decodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder startDecodingInterconnectedObjects]; + [super _decodeContentsWithCoder:aCoder]; + [aCoder finishDecodingInterconnectedObjects]; +} + +- _readInit: (TypedStream*)aStream +{ + [super _readInit:aStream]; + _count = 0; + _contents_root = [self nilNode]; + return self; +} + +- _writeContents: (TypedStream*)aStream +{ + void archiveElement(elt e) + { + objc_write_object(aStream, e.id_u); + } + objc_write_type(aStream, @encode(unsigned int), &_count); + [self withElementsCall:archiveElement]; + // We rely on the nodes to archive their children and parent ptrs; + objc_write_object_reference(aStream, _contents_root); + return self; +} + +- _readContents: (TypedStream*)aStream +{ + int i; + + objc_read_type(aStream, @encode(unsigned int), &_count); + for (i = 0; i < _count; i++) + objc_read_object(aStream, &_contents_root); + // We rely on the nodes to have archived their children and parent ptrs; + objc_read_object(aStream, &_contents_root); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + BinaryTree *copy = [super emptyCopy]; + copy->_count = 0; + copy->_contents_root = [self nilNode]; + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + _count = 0; + _contents_root = [self nilNode]; + return self; +} + +/* Override the designated initializer for our superclass IndexedCollection + to make sure we have object contents */ +- initWithType: (const char *)contentEncoding +{ + if (!ENCODING_IS_OBJECT(contentEncoding)) + [self error:"BinaryTree contents must be objects."]; + return [self init]; +} + +- nilNode +{ + return nilBinaryTreeNode; +} + +- rootNode +{ + return _contents_root; +} + +- leftmostNodeFromNode: aNode +{ + id left; + + if (aNode && aNode != [self nilNode]) + { + while ((left = [aNode leftNode]) != [self nilNode]) + aNode = left; + } + return aNode; +} + +- rightmostNodeFromNode: aNode +{ + id right; + + if (aNode && aNode != [self nilNode]) + while ((right = [aNode rightNode]) != [self nilNode]) + { + aNode = right; + } + return aNode; +} + +- (elt) firstElement +{ + return [self leftmostNodeFromNode:_contents_root]; +} + +- (elt) lastElement +{ + return [self rightmostNodeFromNode:_contents_root]; +} + +/* This is correct only is the tree is sorted. How to deal with this? */ +- (elt) maxElement +{ + return [self rightmostNodeFromNode:_contents_root]; +} + +/* This is correct only is the tree is sorted. How to deal with this? */ +- (elt) minElement +{ + return [self leftmostNodeFromNode:_contents_root]; +} + +// returns [self nilNode] is there is no successor; +- (elt) successorOfElement: (elt)anElement +{ + id tmp; + + // here tmp is the right node; + if ((tmp = [anElement.id_u rightNode]) != [self nilNode]) + return [self leftmostNodeFromNode:tmp]; + // here tmp is the parent; + tmp = [anElement.id_u parentNode]; + while (tmp != [self nilNode] && anElement.id_u == [tmp rightNode]) + { + anElement.id_u = tmp; + tmp = [tmp parentNode]; + } + return tmp; +} + +// I should make sure that [_contents_root parentNode] == [self nilNode]; +// Perhaps I should make [_contents_root parentNode] == binaryTreeObj ??; + +// returns [self nilNode] is there is no predecessor; +- (elt) predecessorElement: (elt)anElement +{ + id tmp; + + // here tmp is the left node; + if ((tmp = [anElement.id_u leftNode]) != [self nilNode]) + return [self rightmostNodeFromNode:tmp]; + // here tmp is the parent; + tmp = [anElement.id_u parentNode]; + while (tmp != [self nilNode] && anElement.id_u == [tmp leftNode]) + { + anElement.id_u = tmp; + tmp = [tmp parentNode]; + } + return tmp; +} + +/* This relies on [_contents_root parentNode] == [self nilNode] */ +- rootFromNode: aNode +{ + id parentNode; + while ((parentNode = [aNode parentNode]) != [self nilNode]) + aNode = parentNode; + return aNode; +} + +/* This relies on [_contents_root parentNode] == [self nilNode] */ +- (unsigned) depthOfNode: aNode +{ + unsigned count = 0; + + if (aNode == nil || aNode == [self nilNode]) + [self error:"in %s, Can't find depth of nil node", sel_get_name(_cmd)]; + do + { + aNode = [aNode parentNode]; + count++; + } + while (aNode != [self nilNode]); + return count; +} + +- (unsigned) heightOfNode: aNode +{ + unsigned leftHeight, rightHeight; + id tmpNode; + + if (aNode == nil || aNode == [self nilNode]) + { + [self error:"in %s, Can't find height of nil node", sel_get_name(_cmd)]; + return 0; + } + else + { + leftHeight = ((tmpNode = [aNode leftNode]) + ? + (1 + [self heightOfNode:tmpNode]) + : + 0); + rightHeight = ((tmpNode = [aNode rightNode]) + ? + (1 + [self heightOfNode:tmpNode]) + : + 0); + return MAX(leftHeight, rightHeight); + } +} + +- (unsigned) nodeCountUnderNode: aNode +{ + unsigned count = 0; + if ([aNode leftNode] != [self nilNode]) + count += 1 + [self nodeCountUnderNode:[aNode leftNode]]; + if ([aNode rightNode] != [self nilNode]) + count += 1 + [self nodeCountUnderNode:[aNode rightNode]]; + return count; +} + +- leftRotateAroundNode: aNode +{ + id y; + + y = [aNode rightNode]; + if (y == [self nilNode]) + return self; + [aNode setRightNode:[y leftNode]]; + if ([y leftNode] != [self nilNode]) + [[y leftNode] setParentNode:aNode]; + [y setParentNode:[aNode parentNode]]; + if ([aNode parentNode] == [self nilNode]) + _contents_root = y; + else + { + if (NODE_IS_LEFTCHILD(aNode)) + [[aNode parentNode] setLeftNode:y]; + else + [[aNode parentNode] setRightNode:y]; + } + [y setLeftNode:aNode]; + [aNode setParentNode:y]; + return self; +} + +- rightRotateAroundNode: aNode +{ + id y; + + y = [aNode leftNode]; + if (y == [self nilNode]) + return self; + [aNode setLeftNode:[y rightNode]]; + if ([y rightNode] != [self nilNode]) + [[y rightNode] setParentNode:aNode]; + [y setParentNode:[aNode parentNode]]; + if ([aNode parentNode] == [self nilNode]) + _contents_root = y; + else + { + if (NODE_IS_RIGHTCHILD(aNode)) + [[aNode parentNode] setRightNode:y]; + else + [[aNode parentNode] setLeftNode:y]; + } + [y setRightNode:aNode]; + [aNode setParentNode:y]; + return self; +} + +- (elt) elementAtIndex: (unsigned)index +{ + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, _count); + ret = [self firstElement]; + // Not very efficient; Should be rewritten; + while (index--) + ret = [self successorOfElement:ret]; + return ret; +} + +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc +{ + id theParent, tmpChild; + + [newElement.id_u setLeftNode:[self nilNode]]; + [newElement.id_u setRightNode:[self nilNode]]; + theParent = [self nilNode]; + tmpChild = _contents_root; + while (tmpChild != [self nilNode]) + { + theParent = tmpChild; + if ((*aFunc)(newElement,theParent) < 0) + tmpChild = [tmpChild leftNode]; + else + tmpChild = [tmpChild rightNode]; + } + [newElement.id_u setParentNode:theParent]; + if (theParent == [self nilNode]) + _contents_root = newElement.id_u; + else + { + if (COMPARE_ELEMENTS(newElement, theParent) < 0) + [theParent setLeftNode:newElement.id_u]; + else + [theParent setRightNode:newElement.id_u]; + } + _count++; + return self; +} + +- addElement: (elt)newElement +{ + // By default insert in sorted order. Is this what we want?; + [self sortAddElement:newElement]; + return self; +} + +// NOTE: This gives you the power to put elements in unsorted order; +- insertElement: (elt)newElement before: (elt)oldElement +{ + id tmp; + + #if SAFE_BinaryTree + if ([self rootFromNode:oldElement.id_u] != _contents_root) + [self error:"in %s, oldElement not in tree!!", sel_get_name(_cmd)]; + #endif + + [newElement.id_u setRightNode:[self nilNode]]; + [newElement.id_u setLeftNode:[self nilNode]]; + if ((tmp = [oldElement.id_u leftNode]) != [self nilNode]) + { + [(tmp = [self rightmostNodeFromNode:tmp]) setRightNode:newElement.id_u]; + [newElement.id_u setParentNode:tmp]; + } + else if (newElement.id_u != [self nilNode]) + { + [oldElement.id_u setLeftNode:newElement.id_u]; + [newElement.id_u setParentNode:oldElement.id_u]; + } + else + { + _contents_root = newElement.id_u; + [newElement.id_u setParentNode:[self nilNode]]; + } + _count++; + return self; +} + +// NOTE: This gives you the power to put elements in unsorted order; +- insertElement: (elt)newElement after: (elt)oldElement +{ + id tmp; + + #if SAFE_BinaryTree + if ([self rootFromNode:oldElement.id_u] != _contents_root) + [self error:"in %s, !!!!!!!!", sel_get_name(_cmd)]; + #endif + + [newElement.id_u setRightNode:[self nilNode]]; + [newElement.id_u setLeftNode:[self nilNode]]; + if ((tmp = [oldElement.id_u rightNode]) != [self nilNode]) + { + [(tmp = [self leftmostNodeFromNode:tmp]) setLeftNode:newElement.id_u]; + [newElement.id_u setParentNode:tmp]; + } + else if (newElement.id_u != [self nilNode]) + { + [oldElement.id_u setRightNode:newElement.id_u]; + [newElement.id_u setParentNode:oldElement.id_u]; + } + else + { + _contents_root = newElement.id_u; + [newElement.id_u setParentNode:[self nilNode]]; + } + _count++; + return self; +} + +// NOTE: This gives you the power to put elements in unsorted order; +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count+1); + if (index == _count) + [self appendElement:newElement]; + else + [self insertElement:newElement before:[self elementAtIndex:index]]; + return self; +} + +// NOTE: This gives you the power to put elements in unsorted order; +- appendElement: (elt)newElement +{ + if (_count == 0) + { + _contents_root = newElement.id_u; + _count = 1; + [newElement.id_u setLeftNode:[self nilNode]]; + [newElement.id_u setRightNode:[self nilNode]]; + [newElement.id_u setParentNode:[self nilNode]]; + } + else + [self insertElement:newElement after:[self lastElement]]; + return self; +} + +- (elt) removeElement: (elt)oldElement +{ + id x, y; + + if ([oldElement.id_u leftNode] == [self nilNode] + || [oldElement.id_u rightNode] == [self nilNode]) + y = oldElement.id_u; + else + y = [self successorOfElement:oldElement].id_u; + + if ([y leftNode] != [self nilNode]) + x = [y leftNode]; + else + x = [y rightNode]; + + [x setParentNode:[y parentNode]]; + + if ([y parentNode] == [self nilNode]) + _contents_root = x; + else + { + if (y == [[y parentNode] leftNode]) + [[y parentNode] setLeftNode:x]; + else + [[y parentNode] setRightNode:x]; + } + + if (y != oldElement.id_u) + { + /* put y in the place of oldElement.id_u */ + [y setParentNode:[oldElement.id_u parentNode]]; + [y setLeftNode:[oldElement.id_u leftNode]]; + [y setRightNode:[oldElement.id_u rightNode]]; + if (oldElement.id_u == [[oldElement.id_u parentNode] leftNode]) + [[oldElement.id_u parentNode] setLeftNode:y]; + else + [[oldElement.id_u parentNode] setRightNode:oldElement.id_u]; + [[oldElement.id_u leftNode] setParentNode:y]; + [[oldElement.id_u rightNode] setParentNode:y]; + } + [oldElement.id_u setRightNode:[self nilNode]]; + [oldElement.id_u setLeftNode:[self nilNode]]; + [oldElement.id_u setParentNode:[self nilNode]]; + _count--; + return oldElement; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag +{ + void traverse(id aNode) + { + if (!(*flag) || aNode == [self nilNode] || !aNode) + return; + traverse([aNode leftNode]); + (*aFunc)(aNode); + traverse([aNode rightNode]); + } + traverse(_contents_root); + return self; +} + +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag +{ + void traverse(id aNode) + { + if (*flag || aNode == [self nilNode] || !aNode) + return; + traverse([aNode rightNode]); + (*aFunc)(aNode); + traverse([aNode leftNode]); + } + traverse(_contents_root); + return self; +} + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + if (!(*enumState)) + *enumState = [self leftmostNodeFromNode:_contents_root]; + else + *enumState = [self successorOfElement:*enumState].id_u; + *anElementPtr = *enumState; + if (*enumState) + return YES; + return NO; +} + +- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + if (!(*enumState)) + *enumState = [self rightmostNodeFromNode:_contents_root]; + else + *enumState = [self predecessorElement:*enumState].id_u; + *anElementPtr = *enumState; + if (*enumState) + return YES; + return NO; +} + +- (unsigned) count +{ + return _count; +} + +/* replace this with something better eventually */ +- _tmpPrintFromNode: aNode indent: (int)count +{ + printf("%-*s", count, ""); + if ([aNode respondsTo:@selector(printForDebugger)]) + [aNode printForDebugger]; + else + printf("?\n"); + printf("%-*s.", count, ""); + if ([aNode leftNode] != [self nilNode]) + [self _tmpPrintFromNode:[aNode leftNode] indent:count+2]; + else + printf("\n"); + printf("%-*s.", count, ""); + if ([aNode rightNode] != [self nilNode]) + [self _tmpPrintFromNode:[aNode rightNode] indent:count+2]; + else + printf("\n"); + return self; +} + +- binaryTreePrintForDebugger +{ + [self _tmpPrintFromNode:_contents_root indent:0]; + return self; +} + +@end + + diff --git a/Source/BinaryTreeEltNode.m b/Source/BinaryTreeEltNode.m new file mode 100644 index 000000000..8007d7d4d --- /dev/null +++ b/Source/BinaryTreeEltNode.m @@ -0,0 +1,39 @@ +/* Implementation for Objective-C BinaryTreeEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation BinaryTreeEltNode + ++ initialize +{ + if (self == [BinaryTreeEltNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +#include + +@end + diff --git a/Source/BinaryTreeNode.m b/Source/BinaryTreeNode.m new file mode 100644 index 000000000..375bb7249 --- /dev/null +++ b/Source/BinaryTreeNode.m @@ -0,0 +1,111 @@ +/* Implementation for Objective-C BinaryTreeNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +@implementation BinaryTreeNode + ++ initialize +{ + if (self == [BinaryTreeNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- init +{ + [super init]; + _left = _right = _parent = nil; + return self; +} + +- (void) encodeWithCoder: (Coder*)aCoder +{ + [super encodeWithCoder:aCoder]; + [aCoder encodeObjectReference:_right withName:"Right BinaryTree Node"]; + [aCoder encodeObjectReference:_left withName:"Left BinaryTree Node"]; + [aCoder encodeObjectReference:_parent withName:"Parent BinaryTree Node"]; +} + ++ newWithCoder: (Coder*)aCoder +{ + BinaryTreeNode *n = [super newWithCoder:aCoder]; + [aCoder decodeObjectAt:&(n->_right) withName:NULL]; + [aCoder decodeObjectAt:&(n->_left) withName:NULL]; + [aCoder decodeObjectAt:&(n->_parent) withName:NULL]; + return n; +} + +- write: (TypedStream*)aStream +{ + [super write:aStream]; + objc_write_object_reference(aStream, _right); + objc_write_object_reference(aStream, _left); + objc_write_object_reference(aStream, _parent); + return self; +} + +- read: (TypedStream*)aStream +{ + [super read:aStream]; + objc_read_object(aStream, &_right); + objc_read_object(aStream, &_left); + objc_read_object(aStream, &_parent); + return self; +} + +- leftNode +{ + return _left; +} + +- rightNode +{ + return _right; +} + +- parentNode +{ + return _parent; +} + +- setLeftNode: aNode +{ + _left = aNode; + return self; +} + +- setRightNode: aNode +{ + _right = aNode; + return self; +} + +- setParentNode: aNode +{ + _parent = aNode; + return self; +} + +@end + diff --git a/Source/CircularArray.m b/Source/CircularArray.m new file mode 100644 index 000000000..5c6431be2 --- /dev/null +++ b/Source/CircularArray.m @@ -0,0 +1,220 @@ +/* Implementation for Objective-C CircularArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include +#include + +@implementation CircularArray + ++ initialize +{ + if (self == [CircularArray class]) + [self setVersion:0]; /* beta release */ + return self; +} + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity +{ + [super initWithType:contentEncoding capacity:aCapacity]; + _start_index = 0; + return self; +} + +/* Archiving must mimic the above designated initializer */ + ++ _newCollectionWithCoder: (Coder*)coder +{ + CircularArray *n = [super newWithCoder:coder]; + n->_start_index = 0; + return n; +} + +- _readInit: (TypedStream*)aStream +{ + [super _readInit: aStream]; + _start_index = 0; + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ + +- emptyCopy +{ + CircularArray *copy = [super emptyCopy]; + copy->_start_index = 0; + return copy; +} + +- empty +{ + [super empty]; + _start_index = 0; + return self; +} + +/* This is the only method that changes the value of the instance + variable _capacity, except for "-initDescription:capacity:" */ + +- setCapacity: (unsigned)newCapacity +{ + elt *new_contents; + int i; + + if (newCapacity > _count) { + /* This could be more efficient */ + OBJC_MALLOC(new_contents, elt, newCapacity); + for (i = 0; i < _count; i++) + new_contents[i] = _contents_array[CIRCULAR_TO_BASIC(i)]; + OBJC_FREE(_contents_array); + _contents_array = new_contents; + _start_index = 0; + _capacity = newCapacity; + } + return self; +} + +- (elt) removeElementAtIndex: (unsigned)index +{ + unsigned basicIndex; + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, _count); + basicIndex = CIRCULAR_TO_BASIC(index); + ret = _contents_array[basicIndex]; + circularFillHoleAt(self, basicIndex); + decrementCount(self); + return ret; +} + +- (elt) removeFirstElement +{ + elt ret; + + ret = _contents_array[_start_index]; + _start_index = (_start_index + 1) % _capacity; + decrementCount(self); + return ret; +} + +- (elt) removeLastElement +{ + elt ret; + + if (!_count) + NO_ELEMENT_FOUND_ERROR(); + ret = _contents_array[CIRCULAR_TO_BASIC(_count-1)]; + decrementCount(self); + return ret; +} + +- (elt) elementAtIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count); + return _contents_array[CIRCULAR_TO_BASIC(index)]; +} + +- appendElement: (elt)newElement +{ + incrementCount(self); + _contents_array[CIRCULAR_TO_BASIC(_count-1)] = newElement; + return self; +} + +- prependElement: (elt)newElement +{ + incrementCount(self); + _start_index = (_capacity + _start_index - 1) % _capacity; + _contents_array[_start_index] = newElement; + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + unsigned basicIndex; + + CHECK_INDEX_RANGE_ERROR(index, _count+1); + incrementCount(self); + basicIndex = CIRCULAR_TO_BASIC(index); + circularMakeHoleAt(self, basicIndex); + _contents_array[basicIndex] = newElement; + return self; +} + +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement +{ + elt ret; + unsigned basicIndex; + + CHECK_INDEX_RANGE_ERROR(index, _count); + basicIndex = CIRCULAR_TO_BASIC(index); + ret = _contents_array[basicIndex]; + _contents_array[basicIndex] = newElement; + return ret; +} + +- swapAtIndeces: (unsigned)index1 : (unsigned)index2 +{ + elt tmp; + + CHECK_INDEX_RANGE_ERROR(index1, _count); + CHECK_INDEX_RANGE_ERROR(index2, _count); + index1 = CIRCULAR_TO_BASIC(index1); + index2 = CIRCULAR_TO_BASIC(index2); + tmp = _contents_array[index1]; + _contents_array[index1] = _contents_array[index2]; + _contents_array[index2] = tmp; + return self; +} + +/* just temporary for debugging +- circularArrayPrintForDebugger +{ + int i; + + printf("_start_index=%d, _count=%d, _capacity=%d\n", + _start_index, _count, _capacity); + for (i = 0; i < _capacity; i++) + { + printf("%3d ", i); + } + printf("\n"); + for (i = 0; i < _capacity; i++) + { + printf("%3d ", _contents_array[i].int_t); + } + printf("\n"); + for (i = 0; i < _capacity; i++) + { + printf("%3d ", _contents_array[CIRCULAR_TO_BASIC(i)].int_t); + } + printf("\n"); + + return self; +} +*/ + +@end + diff --git a/Source/Coder.m b/Source/Coder.m new file mode 100644 index 000000000..17994e533 --- /dev/null +++ b/Source/Coder.m @@ -0,0 +1,1299 @@ +/* Implementation of GNU Objective-C coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CODER_FORMAT_VERSION 0 + +enum {CODER_OBJECT_NIL = 0, CODER_OBJECT, CODER_ROOT_OBJECT, + CODER_REPEATED_OBJECT, CODER_CLASS_OBJECT, + CODER_OBJECT_FORWARD_REFERENCE, + CODER_CLASS_NIL, CODER_CLASS, CODER_REPEATED_CLASS, + CODER_CONST_PTR_NULL, CODER_CONST_PTR, CODER_REPEATED_CONST_PTR}; + +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) + +static BOOL debug_coder = NO; +static id defaultStreamClass; + +/* xxx For experimentation. The function in objc-api.h doesn't always + work for objects; it sometimes returns YES for an instance. */ + +/* But, metaclasses return YES too? */ +static BOOL +my_object_is_class(id object) +{ + if (object != nil +#if NeXT_runtime + && CLS_ISMETA(((Class)object)->isa) + && ((Class)object)->isa != ((Class)object)->isa) +#else + && CLS_ISMETA(((Class*)object)->class_pointer) + && ((Class*)object)->class_pointer != ((Class*)object)->class_pointer) +#endif + return YES; + else + return NO; +} + + +@implementation Coder + ++ initialize +{ + if (self == [Coder class]) + { + defaultStreamClass = [MemoryStream class]; + assert(sizeof(void*) == sizeof(unsigned)); + } + return self; +} + ++ setDebugging: (BOOL)f +{ + debug_coder = f; + return self; +} + ++ (void) setDefaultStreamClass: sc +{ + defaultStreamClass = sc; +} + ++ defaultStreamClass +{ + return defaultStreamClass; +} + +/* Careful, this shouldn't contain newlines */ ++ (const char *) coderSignature +{ + return "GNU Objective C Class Library Coder"; +} + ++ (int) coderFormatVersion +{ + return CODER_FORMAT_VERSION; +} + ++ (int) coderConcreteFormatVersion +{ + [self notImplemented:_cmd]; + return 0; +} + +- (void) encodeSignature +{ + [stream writeLine:[[self class] coderSignature]]; + [self encodeValueOfSimpleType:@encode(int) + at:&format_version + withName:"Coder Format Version"]; + [self encodeValueOfSimpleType:@encode(int) + at:&concrete_format_version + withName:"Coder Concrete Format Version"]; +} + +- (void) decodeSignature +{ + char *s; + + s = [stream readLine]; + if (strcmp(s, [[self class] coderSignature])) + [self error:"Signature mismatch, executable (%s) != encoded (%s)", + [[self class] coderSignature], s]; + (*objc_free)(s); + + [self decodeValueOfSimpleType:@encode(int) + at:&format_version + withName:NULL]; + if (format_version != [[self class] coderFormatVersion]) + [self error:"Format version mismatch, executable %d != encoded %d\n", + [[self class] coderFormatVersion], format_version]; + + [self decodeValueOfSimpleType:@encode(int) + at:&concrete_format_version + withName:NULL]; + if (concrete_format_version != [[self class] coderConcreteFormatVersion]) + [self error:"Concrete format version mismatch, " + "executable %d != encoded %d\n", + [[self class] coderConcreteFormatVersion], concrete_format_version]; +} + +/* This is the designated sub-initializer. + Don't call it yourself. + Do override it and call [super...] in subclasses. */ +- doInitOnStream: (Stream*)s isDecoding: (BOOL)f +{ + is_decoding = f; + doing_root_object = NO; + // [s retain]; + stream = s; + object_table = nil; + const_ptr_table = [[Dictionary alloc] initWithType:@encode(void*) + keyType:@encode(unsigned)]; + root_object_tables = nil; + forward_object_tables = nil; + return self; +} + +/* These are the two designated initializers for users. + Should I combine them and differentiate encoding/decoding with + an argument, just like doInitOnStream... does? */ + +- initEncodingOnStream: (Stream *)s +{ + [self doInitOnStream:s isDecoding:NO]; + format_version = [[self class] coderFormatVersion]; + concrete_format_version = [[self class] coderConcreteFormatVersion]; + [self encodeSignature]; + return self; +} + +- initDecodingOnStream: (Stream *)s +{ + [self doInitOnStream:s isDecoding:YES]; + [self decodeSignature]; + return self; +} + +- initEncoding +{ + return [self initEncodingOnStream:[[defaultStreamClass alloc] init]]; +} + +- initDecoding +{ + return [self initDecodingOnStream:[[defaultStreamClass alloc] init]]; +} + +- init +{ + return [self initEncoding]; +} + +/* These _coder... methods may be overriden by subclasses so that + cross-references can be kept differently. + + For instance, ConnectedCoder keeps cross-references to const + pointers on a per-Connection basis instead of a per-Coder basis. + We avoid encoding/decoding the same classes and selectors over and + over again. +*/ + +static inline id +new_object_table() +{ + return [[Dictionary alloc] initWithType:@encode(void*) + keyType:@encode(unsigned)]; +} + +- (BOOL) _coderHasObjectReference: (unsigned)xref +{ + if (!object_table) + object_table = new_object_table(); + return [object_table includesKey:xref]; +} + +- _coderObjectAtReference: (unsigned)xref; +{ + if (!object_table) + object_table = new_object_table(); + return [object_table elementAtKey:xref].id_u; +} + +- (void) _coderPutObject: anObj atReference: (unsigned)xref +{ + if (!object_table) + object_table = new_object_table(); + [object_table putElement:anObj atKey:xref]; +} + +/* Using the next three methods, subclasses can change the way that + const pointers (like SEL, Class, Atomic strings, etc) are + archived. */ + +/* Only use _coderHasConstPtrReference during encoding, not decoding. + Otherwise you'll confuse ConnectedCoder that distinguishes between + incoming and outgoing tables. xxx What am I talking about here?? */ + +- (BOOL) _coderHasConstPtrReference: (unsigned)xref +{ + return [const_ptr_table includesKey:xref]; +} + +static elt +exc_return_null(arglist_t f) +{ + return (void*)0; +} + +- (const void*) _coderConstPtrAtReference: (unsigned)xref; +{ + return [const_ptr_table elementAtKey:xref + ifAbsentCall:exc_return_null].void_ptr_u; +} + +- (void) _coderPutConstPtr: (const void*)p atReference: (unsigned)xref +{ + assert(![const_ptr_table includesKey:xref]); + [const_ptr_table putElement:(void*)p atKey:xref]; +} + +/* Here are the methods for root objects */ + +- (void) _coderPushRootObjectTable +{ + if (!root_object_tables) + root_object_tables = [[Stack alloc] init]; + [root_object_tables pushObject: + [[Dictionary alloc] initWithType:@encode(void*) + keyType:@encode(unsigned)]]; +} + +- (void) _coderPopRootObjectTable +{ + assert(root_object_tables); + [[root_object_tables popObject] free]; +} + +- _coderTopRootObjectTable +{ + assert(root_object_tables); + return [root_object_tables topObject]; +} + +/* Here are the methods for forward object references. */ + +- (void) _coderPushForwardObjectTable +{ + if (!forward_object_tables) + forward_object_tables = [[Stack alloc] init]; + [forward_object_tables pushObject: + [[Dictionary alloc] initWithType:@encode(void*) + keyType:@encode(unsigned)]]; +} + +- (void) _coderPopForwardObjectTable +{ + assert(forward_object_tables); + [[forward_object_tables popObject] free]; +} + +- _coderTopForwardObjectTable +{ + assert(forward_object_tables); + return [forward_object_tables topObject]; +} + +- (struct objc_list *) _coderForwardObjectsAtReference: (unsigned)xref +{ + assert(forward_object_tables); + return (struct objc_list*) + [[forward_object_tables topObject] elementAtKey:xref + ifAbsentCall:exc_return_null].void_ptr_u; +} + +- (void) _coderPutForwardObjects: (struct objc_list *)head + atReference: (unsigned)xref +{ + assert(forward_object_tables); + [[forward_object_tables topObject] putElement:head atKey:xref]; +} + + +/* This is the Coder's interface to the over-ridable + "_coderPutObject:atReference" method. Do not override it. It + handles the root_object_table. */ + +- (void) _internalCoderPutObject: anObj atReference: (unsigned)xref +{ + if (doing_root_object) + { + assert(![[self _coderTopRootObjectTable] includesKey:xref]); + [[self _coderTopRootObjectTable] putElement:anObj atKey:xref]; + } + [self _coderPutObject:anObj atReference:xref]; +} + +- (BOOL) isDecoding +{ + return is_decoding; +} + +- (void) encodeTag: (unsigned char)t +{ + [self encodeValueOfSimpleType:@encode(unsigned char) + at:&t + withName:"Coder tag"]; +} + +- (unsigned char) decodeTag +{ + unsigned char t; + [self decodeValueOfSimpleType:@encode(unsigned char) + at:&t + withName:NULL]; + return t; +} + +- (void) encodeClass: aClass +{ + [self encodeIndent]; + if (aClass == Nil) + { + [self encodeTag: CODER_CLASS_NIL]; + } + else + { + unsigned xref = PTR2LONG(aClass); + if ([self _coderHasConstPtrReference:xref]) + { + [self encodeTag: CODER_REPEATED_CLASS]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"Class cross-reference number"]; + } + else + { + const char *class_name = class_get_class_name(aClass); + int class_version = class_get_version(aClass); + + assert(class_name); + assert(*class_name); + [self encodeTag: CODER_CLASS]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"Class cross-reference number"]; + [self encodeValueOfSimpleType:@encode(char*) + at:&class_name + withName:"Class name"]; + [self encodeValueOfSimpleType:@encode(int) + at:&class_version + withName:"Class version"]; + [self _coderPutConstPtr:aClass atReference:xref]; + } + } + [self encodeUnindent]; + return; +} + +- decodeClass +{ + unsigned char tag; + char *class_name; + int class_version; + id ret = Nil; + + [self decodeIndent]; + tag = [self decodeTag]; + switch (tag) + { + case CODER_CLASS_NIL: + break; + case CODER_CLASS: + { + unsigned xref; + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + [self decodeValueOfSimpleType:@encode(char*) + at:&class_name + withName:NULL]; + [self decodeValueOfSimpleType:@encode(int) + at:&class_version + withName:NULL]; + ret = objc_lookup_class(class_name); + if (ret == Nil) + [self error:"Couldn't find class `%s'", class_name]; + if (class_get_version(ret) != class_version) + [self error:"Class version mismatch, executable %d != encoded %d", + class_get_version(ret), class_version]; + if ([self _coderHasConstPtrReference:xref]) + [self error:"two classes have the same cross-reference number"]; + [self _coderPutConstPtr:ret atReference:xref]; + if (debug_coder) + fprintf(stderr, "Coder decoding registered class xref %u\n", xref); + (*objc_free)(class_name); + break; + } + case CODER_REPEATED_CLASS: + { + unsigned xref; + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + ret = (id) [self _coderConstPtrAtReference:xref]; + if (!ret) + [self error:"repeated class cross-reference number %u not found", + xref]; + break; + } + default: + [self error:"unrecognized class tag = %d", (int)tag]; + } + [self decodeUnindent]; + return ret; +} + +- (void) encodeAtomicString: (const char*)sp + withName: (const char*)name +{ + /* xxx Add repeat-string-ptr checking here. */ + [self notImplemented:_cmd]; + [self encodeValueOfSimpleType:@encode(char*) at:&sp withName:name]; +} + +- (const char *) decodeAtomicStringWithName: (const char **)name +{ + char *s; + /* xxx Add repeat-string-ptr checking here */ + [self notImplemented:_cmd]; + [self decodeValueOfSimpleType:@encode(char*) at:&s withName:name]; + return s; +} + +#define NO_SEL_TYPES "none" + +- (void) encodeSelector: (SEL)sel withName: (const char*)name +{ + [self encodeName:name]; + [self encodeIndent]; + if (sel == 0) + { + [self encodeTag: CODER_CONST_PTR_NULL]; + } + else + { + unsigned xref = PTR2LONG(sel); + if ([self _coderHasConstPtrReference:xref]) + { + [self encodeTag: CODER_REPEATED_CONST_PTR]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"SEL cross-reference number"]; + } + else + { + const char *sel_name; + const char *sel_types; + + [self encodeTag: CODER_CONST_PTR]; + sel_name = sel_get_name(sel); +#if NeXT_runtime + sel_types = NO_SEL_TYPES; +#else + sel_types = sel_get_type(sel); +#endif +#if 0 + /* xxx Think about something like this. */ + if (!sel_types) + sel_types = sel_get_type(sel_get_any_uid(sel_get_name(sel))); +#endif + if (!sel_name) [self error:"ObjC runtime didn't provide SEL name"]; + if (!*sel_name) [self error:"ObjC runtime didn't provide SEL name"]; + if (!sel_types) [self error:"ObjC runtime didn't provide SEL type"]; + if (!*sel_types) [self error:"ObjC runtime didn't provide SEL type"]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"SEL cross-reference number"]; + [self encodeValueOfSimpleType:@encode(char*) + at:&sel_name + withName:"SEL name"]; + [self encodeValueOfSimpleType:@encode(char*) + at:&sel_types + withName:"SEL types"]; + [self _coderPutConstPtr:sel atReference:xref]; + if (debug_coder) + fprintf(stderr, "Coder encoding registered sel xref %u\n", xref); + } + } + [self encodeUnindent]; + return; +} + +- (SEL) decodeSelectorWithName: (const char **)name +{ + char tag; + SEL ret = NULL; + + [self decodeName:name]; + [self decodeIndent]; + tag = [self decodeTag]; + switch (tag) + { + case CODER_CONST_PTR_NULL: + break; + case CODER_CONST_PTR: + { + unsigned xref; + char *sel_name; + char *sel_types; + + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + [self decodeValueOfSimpleType:@encode(char *) + at:&sel_name + withName:NULL]; + [self decodeValueOfSimpleType:@encode(char *) + at:&sel_types + withName:NULL]; +#if NeXT_runtime + ret = sel_getUid(sel_name); +#else + if (!strcmp(sel_types, NO_SEL_TYPES)) + ret = sel_get_any_uid(sel_name); + else + ret = sel_get_typed_uid(sel_name, sel_types); +#endif + if (!ret) + [self error:"Could not find selector (%s) with types [%s]", + sel_name, sel_types]; +#if ! NeXT_runtime + if (strcmp(sel_types, NO_SEL_TYPES) + && !(sel_types_match(sel_types, ret->sel_types))) + [self error:"ObjC runtime didn't provide SEL with matching type"]; +#endif + [self _coderPutConstPtr:ret atReference:xref]; + if (debug_coder) + fprintf(stderr, "Coder decoding registered sel xref %u\n", xref); + (*objc_free)(sel_name); + (*objc_free)(sel_types); + break; + } + case CODER_REPEATED_CONST_PTR: + { + unsigned xref; + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + ret = (SEL)[self _coderConstPtrAtReference:xref]; + if (!ret) + [self error:"repeated selector cross-reference number %u not found", + xref]; + break; + } + default: + [self error:"unrecognized selector tag = %d", (int)tag]; + } + [self decodeUnindent]; + return ret; +} + +- (void) encodeValueOfType: (const char*)type + at: (const void*)d + withName: (const char *)name +{ + switch (*type) + { + case _C_CLASS: + [self encodeName:name]; + [self encodeClass: *(id*)d]; + break; + case _C_ATOM: + [self encodeAtomicString:*(char**)d withName:name]; + break; + case _C_SEL: + { + [self encodeSelector:*(SEL*)d withName:name]; + break; + } + case _C_ID: + [self encodeObject:*(id*)d withName:name]; + break; + case _C_ARY_B: + { + int len = atoi(type+1); /* xxx why +1 ? */ + int offset; + + while (isdigit(*++type)); + offset = objc_sizeof_type(type); + [self encodeName:name]; + [self encodeIndent]; + while (len-- > 0) + { + [self encodeValueOfType:type + at:d + withName:"array component"]; + ((char*)d) += offset; + } + [self encodeUnindent]; + break; + } + case _C_STRUCT_B: + { + int acc_size = 0; + int align; + + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + [self encodeName:name]; + [self encodeIndent]; + while (*type != _C_STRUCT_E) + { + align = objc_alignof_type (type); /* pad to alignment */ + acc_size = ROUND (acc_size, align); + [self encodeValueOfType:type + at:((char*)d)+acc_size + withName:"structure component"]; + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + [self encodeUnindent]; + break; + } + case _C_PTR: + [self error:"Cannot encode pointers"]; + break; +#if 0 /* No, don't know how far to recurse */ + [self encodeValueOfType:type+1 at:*(char**)d withName:name]; + break; +#endif + default: + [self encodeValueOfSimpleType:type at:d withName:name]; + } +} + +- (void) encodeValueOfSimpleType: (const char*)type + at: (const void*)d + withName: (const char *)name +{ + [self notImplemented:_cmd]; +} + +- (void) decodeValueOfType: (const char*)type + at: (void*)d + withName: (const char **)namePtr +{ + switch (*type) + { + case _C_CLASS: + { + [self decodeName:namePtr]; + *(id*)d = [self decodeClass]; + break; + } + case _C_ATOM: + *(const char**)d = [self decodeAtomicStringWithName:namePtr]; + break; + case _C_SEL: + *(SEL*)d = [self decodeSelectorWithName:namePtr]; + break; + case _C_ID: + [self decodeObjectAt:d withName:namePtr]; + break; + case _C_ARY_B: + { + /* xxx Do we need to allocate space, just like _C_CHARPTR ? */ + int len = atoi(type+1); + int offset; + [self decodeName:namePtr]; + [self decodeIndent]; + while (isdigit(*++type)); + offset = objc_sizeof_type(type); + while (len-- > 0) + { + [self decodeValueOfType:type + at:d + withName:namePtr]; + ((char*)d) += offset; + } + [self decodeUnindent]; + break; + } + case _C_STRUCT_B: + { + /* xxx Do we need to allocate space just like char* ? No. */ + int acc_size = 0; + int align; + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + [self decodeName:namePtr]; + [self decodeIndent]; /* xxx insert [self decodeName:] */ + while (*type != _C_STRUCT_E) + { + align = objc_alignof_type (type); /* pad to alignment */ + acc_size = ROUND (acc_size, align); + [self decodeValueOfType:type + at:((char*)d)+acc_size + withName:namePtr]; + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + [self decodeUnindent]; + break; + } + case _C_PTR: + [self error:"Cannot decode pointers"]; + break; +#if 0 /* No, don't know how far to recurse */ + OBJC_MALLOC(*(void**)d, void*, 1); + [self decodeValueOfType:type+1 at:*(char**)d withName:namePtr]; + break; +#endif + default: + [self decodeValueOfSimpleType:type at:d withName:namePtr]; + } + /* xxx We need to catch unions and make a sensible error message */ +} + +- (void) decodeValueOfSimpleType: (const char*)type + at: (void*)d + withName: (const char **)namePtr +{ + [self notImplemented:_cmd]; +} + +- (void) encodeBytes: (const char *)b + count: (unsigned)c + withName: (const char *)name +{ + [self notImplemented:_cmd]; +} + +- (void) decodeBytes: (char *)b + count: (unsigned*)c + withName: (const char **)name +{ + [self notImplemented:_cmd]; +} + +- (void) startEncodingInterconnectedObjects +{ + doing_root_object = YES; + [self _coderPushRootObjectTable]; + [self _coderPushForwardObjectTable]; +} + +- (void) finishEncodingInterconnectedObjects +{ + /* xxx Perhaps we should look at the forward references and + encode here any forward-referenced objects that haven't been + encoded yet. */ + doing_root_object = NO; + [self _coderPopRootObjectTable]; + [self _coderPopForwardObjectTable]; +} + +- (void) startDecodingInterconnectedObjects +{ + doing_root_object = YES; + [self _coderPushRootObjectTable]; + [self _coderPushForwardObjectTable]; +} + +- (void) finishDecodingInterconnectedObjects +{ + SEL awake_sel = sel_get_any_uid("awakeAfterUsingCoder:"); + + /* resolve object forward references */ + if (forward_object_tables) + { + void set_obj_addrs_for_xref(elt key, elt content) + { + const struct objc_list *addr_list = content.void_ptr_u; + id object = [self _coderObjectAtReference:key.unsigned_int_u]; + /* If reference isn't there, object will be nil, and all the + forward references to that object will be set to nil. + I suppose this is fine. */ + while (addr_list) + { + *((id*)(addr_list->head)) = object; + addr_list = addr_list->tail; + } + } + [[self _coderTopForwardObjectTable] + withKeyElementsAndContentElementsCall:set_obj_addrs_for_xref]; + [self _coderPopForwardObjectTable]; + } + + /* call awake all the objects read */ + if (awake_sel) + { + void ask_awake(elt e) + { + if (__objc_responds_to(e.id_u, awake_sel)) + (*objc_msg_lookup(e.id_u,awake_sel))(e.id_u, awake_sel, self); + } + [[self _coderTopRootObjectTable] withElementsCall:ask_awake]; + } + [self _coderPopRootObjectTable]; + doing_root_object = NO; +} + +/* NOTE: This *can* be called recursively */ +- (void) encodeRootObject: anObj + withName: (const char *)name +{ + [self encodeTag:CODER_ROOT_OBJECT]; + [self startEncodingInterconnectedObjects]; + [self encodeIndent]; + [self encodeObject:anObj withName:name]; + [self encodeUnindent]; + [self finishEncodingInterconnectedObjects]; +} + +- (void) _decodeRootObjectAt: (id*)ret withName: (const char **)name +{ + [self startDecodingInterconnectedObjects]; + [self decodeIndent]; + [self decodeObjectAt:ret withName:name]; + [self decodeUnindent]; + [self finishDecodingInterconnectedObjects]; +} + + +/* These two methods are the designated coder methods called when + we've determined that the object has not already been + encoded---we're not simply going to encode a cross-reference number + to the object, we're actually going to encode an object (either a + proxy to the object or the object itself). + + ConnectedCoder overrides _doEncodeObject: in order to implement + the encoding of proxies. */ + +- (void) _doEncodeBycopyObject: anObj +{ + [self encodeClass:object_get_class(anObj)]; + /* xxx Make sure it responds to this selector! */ + [anObj encodeWithCoder:self]; +} + +/* This method overridden by ConnectedCoder */ +- (void) _doEncodeObject: anObj +{ + [self _doEncodeBycopyObject:anObj]; +} + + +/* This is the designated object encoder */ +- (void) _encodeObject: anObj + withName: (const char*) name + isBycopy: (BOOL) bycopy_flag + isForwardReference: (BOOL) forward_ref_flag +{ + [self encodeName:name]; + [self encodeIndent]; + if (!anObj) + { + [self encodeTag:CODER_OBJECT_NIL]; + } + else if (my_object_is_class(anObj)) + { + [self encodeTag:CODER_CLASS_OBJECT]; + [self encodeClass:anObj]; + } + else + { + unsigned xref = PTR2LONG(anObj); + if ([self _coderHasObjectReference:xref]) + { + [self encodeTag:CODER_REPEATED_OBJECT]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"Object cross-reference number"]; + } + else if (forward_ref_flag) + { + [self encodeTag:CODER_OBJECT_FORWARD_REFERENCE]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"Object forward cross-reference number"]; + } + else + { + [self _internalCoderPutObject:anObj atReference:xref]; + [self encodeTag:CODER_OBJECT]; + [self encodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:"Object cross-reference number"]; + [self encodeIndent]; + if (bycopy_flag) + [self _doEncodeBycopyObject:anObj]; + else + [self _doEncodeObject:anObj]; + [self encodeUnindent]; + } + } + [self encodeUnindent]; +} + +- (void) encodeObject: anObj + withName: (const char *)name +{ + [self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:NO]; +} + + +- (void) encodeObjectBycopy: anObj + withName: (const char *)name +{ + [self _encodeObject:anObj withName:name isBycopy:YES isForwardReference:NO]; +} + +- (void) encodeObjectReference: anObj + withName: (const char *)name +{ + [self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:YES]; +} + + +/* This is the designated (and one-and-only) object decoder */ +- (void) decodeObjectAt: (id*)anObjPtr withName: (const char**)name +{ + unsigned char tag; + + [self decodeName:name]; + [self decodeIndent]; + tag = [self decodeTag]; + switch (tag) + { + case CODER_OBJECT_NIL: + *anObjPtr = nil; + break; + case CODER_CLASS_OBJECT: + *anObjPtr = [self decodeClass]; + break; + case CODER_OBJECT: + { + unsigned xref; + SEL decode_sel = sel_get_any_uid("newWithCoder:"); + CLASS object_class; + IMP imp; + + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + [self decodeIndent]; + object_class = [self decodeClass]; + if ((imp = objc_msg_lookup(object_class, decode_sel))) + *anObjPtr = (*imp)(object_class, decode_sel, self); + else + *anObjPtr = class_create_instance(object_class); + /* Would get error here with Connection-wide object references + because addProxy gets called in +newRemote:connection: */ + if ([self _coderHasObjectReference:xref]) + [self error:"two objects have the same cross-reference number"]; + if (debug_coder) + fprintf(stderr, "Coder decoding registered class xref %u\n", xref); + [self _internalCoderPutObject:*anObjPtr atReference:xref]; + [self decodeUnindent]; + break; + } + case CODER_ROOT_OBJECT: + { + doing_root_object = YES; + [self _decodeRootObjectAt:anObjPtr withName:name]; + doing_root_object = NO; + break; + } + case CODER_REPEATED_OBJECT: + { + unsigned xref; + + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + *anObjPtr = [self _coderObjectAtReference:xref]; + if (!*anObjPtr) + [self error:"repeated object cross-reference number %u not found", + xref]; + break; + } + case CODER_OBJECT_FORWARD_REFERENCE: + { + unsigned xref; + struct objc_list* addr_list; + + if (!doing_root_object) + [self error:"can't decode forward reference when not decoding " + "a root object"]; + [self decodeValueOfSimpleType:@encode(unsigned) + at:&xref + withName:NULL]; + addr_list = [self _coderForwardObjectsAtReference:xref]; + [self _coderPutForwardObjects:list_cons(anObjPtr,addr_list) + atReference:xref]; + break; + } + default: + [self error:"unrecognized object tag = %d", (int)tag]; + } + [self decodeUnindent]; +} + +- (void) encodeWithName: (const char *)name + valuesOfTypes: (const char *)types, ... +{ + va_list ap; + + [self encodeName:name]; + va_start(ap, types); + while (*types) + { + [self encodeValueOfType:types + at:va_arg(ap, void*) + withName:"Encoded Types Component"]; + types = objc_skip_typespec(types); + } + va_end(ap); +} + +- (void) decodeWithName: (const char **)name + valuesOfTypes: (const char *)types, ... +{ + va_list ap; + + [self decodeName:name]; + va_start(ap, types); + while (*types) + { + [self decodeValueOfType:types + at:va_arg(ap, void*) + withName:NULL]; + types = objc_skip_typespec(types); + } + va_end(ap); +} + +- (void) encodeValueOfTypes: (const char *)types + at: (const void *)d + withName: (const char *)name +{ + [self encodeName:name]; + while (*types) + { + [self encodeValueOfType:types + at:d + withName:"Encoded Types Component"]; + types = objc_skip_typespec(types); + } +} + +- (void) decodeValueOfTypes: (const char *)types + at: (void *)d + withName: (const char **)name +{ + [self decodeName:name]; + while (*types) + { + [self decodeValueOfType:types + at:d + withName:NULL]; + types = objc_skip_typespec(types); + } +} + +- (void) encodeArrayOfType: (const char *)type + at: (const void *)d + count: (unsigned)c + withName: (const char *)name +{ + int i; + int offset = objc_sizeof_type(type); + const char *where = d; + + [self encodeName:name]; + [self encodeValueOfType:@encode(unsigned) at:&c withName:"Array Count"]; + for (i = 0; i < c; i++) + { + [self encodeValueOfType:type + at:where + withName:"Encoded Array Component"]; + where += offset; + } +} + +- (void) decodeArrayOfType: (const char *)type + at: (void *)d + count: (unsigned *)c + withName: (const char **)name +{ + int i; + int offset = objc_sizeof_type(type); + char *where = d; + + [self decodeName:name]; + [self decodeValueOfType:@encode(unsigned) at:c withName:NULL]; + for (i = 0; i < *c; i++) + { + [self decodeValueOfType:type + at:where + withName:NULL]; + where += offset; + } +} + +- free +{ + /* xxx No. [self _finishDecodeRootObject]; */ + [const_ptr_table free]; + [object_table free]; + [[forward_object_tables freeObjects] free]; + [[root_object_tables freeObjects] free]; + [stream free]; /* xxx should we do this? */ + return [super free]; +} + +- (void) encodeIndent +{ + /* Do nothing */ +} + +- (void) encodeUnindent +{ + /* Do nothing */ +} + +- (void) decodeIndent +{ + /* Do nothing */ +} + +- (void) decodeUnindent +{ + /* Do nothing */ +} + +- (void) encodeName: (const char*)n +{ + /* Do nothing */ +} + +- (void) decodeName: (const char**)n +{ + if (n) + { + OBJC_MALLOC(*n, char, 1); + **(char**)n = '\0'; +#if 0 + { + /* xxx fix this junk */ + char *foo = *(char**)n; + foo[0] = '\0'; + } +#endif + } +} + +- (int) coderFormatVersion +{ + return format_version; +} + +- (int) coderConcreteFormatVersion +{ + return concrete_format_version; +} + +- (void) resetCoder +{ + /* xxx Finish this */ + [const_ptr_table empty]; +} + +@end + + +/* Here temporarily until GCC category bug is fixed */ +#include +#include +#include + + +/* Eventually put these directly in Object */ + +/* By combining these, we're working around the GCC 2.6 bug that + causes not all the categories to be processed by the runtime. */ + +@implementation Object (CoderAdditions) + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + /* Do nothing */ +} + ++ newWithCoder: (Coder*)aDecoder +{ + return class_create_instance(self); +} + + + +/* @implementation Object (ConnectionRequests) */ + + +/* By default, Object's encode themselves as proxies across Connection's */ +- classForConnectedCoder:aRmc +{ + return [[aRmc connection] proxyClass]; +} + +/* But if any object overrides the above method to return [Object class] + instead, the Object implementation of the coding method will actually + encode the object itself, not a proxy */ ++ (void) encodeObject: anObject withConnectedCoder: aRmc +{ + [anObject encodeWithCoder:aRmc]; +} + + +/* @implementation Object (Retaining) */ + +- (id) retain +{ + return self; +} + +- (oneway void) release +{ + /* Do nothing */ +} + +- (void) dealloc +{ + /* Do nothing */ +} + +- (unsigned) retainCount +{ + return 0; +} + + +/* @implementation Object (IsProxy) */ + +- (BOOL) isProxy +{ + return NO; +} + +@end + + diff --git a/Source/Collection.m b/Source/Collection.m new file mode 100644 index 000000000..ef4c22803 --- /dev/null +++ b/Source/Collection.m @@ -0,0 +1,1334 @@ +/* Implementation for Objective-C Collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include /* for -contentsEqual: */ +#include /* for -safeWithElementsCall: */ +#include + +@implementation Collection + ++ initialize +{ + if (self == [Collection class]) + { + [self setVersion:0]; // beta release; + } + return self; +} + +// INITIALIZING AND FREEING; + +// This is the designated initializer of this class; +- initWithType:(const char *)contentEncoding +{ + [super init]; + if (!elt_get_comparison_function(contentEncoding)) + [self error:"There is no elt comparison function for type encoding %s", + contentEncoding]; + return self; +} + +- init +{ + // default contents are objects; + return [self initWithType:@encode(id)]; +} + +/* Subclasses can override this for efficiency. For example, Array can + init itself with enough capacity to hold aCollection. */ +- initWithContentsOf: (id )aCollection +{ + [self initWithType:[aCollection contentType]]; + [self addContentsOf:aCollection]; + return self; +} + +- free +{ + // ?; + return [super free]; +} + +/* May be inefficient. Could be overridden; */ +- freeObjects +{ + if (CONTAINS_OBJECTS) + [self safeMakeObjectsPerform:@selector(free)]; + [self empty]; + return self; +} + +// ADDING; + +- addElement: (elt)newElement +{ + return [self subclassResponsibility:_cmd]; +} + +- addElementIfAbsent: (elt)newElement +{ + if (![self includesElement:newElement]) + return [self addElement:newElement]; + return nil; +} + +- addContentsOf: (id )aCollection +{ + id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(addElement:)); + + void doIt(elt e) + { + (*addElementImp)(self, @selector(addElement:), e); + } + + [aCollection withElementsCall:doIt]; + return self; +} + +- addContentsOfIfAbsent: (id )aCollection +{ + id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(addElement:)); + BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(includesElement:)); + + void doIt(elt e) + { + if (!((*includesElementImp)(self, @selector(includesElement), e))) + (*addElementImp)(self, @selector(addElement:), e); + } + + [aCollection withElementsCall:doIt]; + return self; +} + +- addElementsCount: (unsigned)count, ... +{ + va_list ap; + + // could use objc_msg_lookup here also; + va_start(ap, count); + while (count--) + [self addElement:va_arg(ap, elt)]; + va_end(ap); + return self; +} + + +// REMOVING AND REPLACING; + +- (elt) removeElement: (elt)oldElement +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(oldElement); + } + return [self removeElement:oldElement ifAbsentCall:err]; +} + +- (elt) removeElement: (elt)oldElement ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + return [self subclassResponsibility:_cmd]; +} + + +- removeAllOccurrencesOfElement: (elt)oldElement +{ + BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(includesElement:)); + elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(removeElement:)); + + while ((*includesElementImp)(self, @selector(includesElement:), oldElement)) + { + (*removeElementImp)(self, @selector(removeElement:), oldElement); + } + return self; +} + +- removeContentsIn: (id )aCollection +{ + BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(includesElement:)); + elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(removeElement:)); + + void doIt(elt e) + { + if ((*includesElementImp)(self, @selector(includesElement:), e)) + (*removeElementImp)(self, @selector(removeElement:), e); + } + + [aCollection withElementsCall:doIt]; + return self; +} + +- removeContentsNotIn: (id )aCollection +{ + BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) + objc_msg_lookup(aCollection, @selector(includesElement:)); + elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(removeElement:)); + + void doIt(elt e) + { + if (!(*includesElementImp)(aCollection, @selector(includesElement:), e)) + (*removeElementImp)(self, @selector(removeElement:), e); + } + + [self safeWithElementsCall:doIt]; + return self; +} + +// remember this has to be overridden for IndexedCollection's; +- (elt) replaceElement: (elt )oldElement with: (elt )newElement + ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + elt err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + elt ret; + ret = [self removeElement:oldElement ifAbsentCall:err]; + [self addElement:newElement]; + return ret; +} + +- (elt) replaceElement: (elt )oldElement with: (elt)newElement +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(oldElement); + } + return [self replaceElement:oldElement with:newElement + ifAbsentCall:err]; +} + +- replaceAllOccurrencesOfElement: (elt)oldElement with: (elt)newElement +{ + BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) + objc_msg_lookup(self, @selector(includesElement:)); + elt (*replaceElementImp)(id,SEL,elt,elt) = (elt(*)(id,SEL,elt,elt)) + objc_msg_lookup(self, @selector(replaceElement:with:)); + + if (ELEMENTS_EQUAL(oldElement, newElement)) + return self; + while ((*includesElementImp)(self,@selector(includesElement:),oldElement)) + (*replaceElementImp)(self,@selector(replaceElement:with:), + oldElement, newElement); + return self; +} + +/* This is pretty inefficient? Try to come up with something better. */ +- uniqueContents +{ + // Use objc_msg_lookup here also; + void doIt(elt e) + { + while ([self occurrencesOfElement:e] > 1) + [self removeElement:e]; + } + [self safeWithElementsCall:doIt]; + return self; +} + +/* This must work without sending any messages to content objects. + Content objects already may be -free'd when this is executed. */ +- empty +{ + [self subclassResponsibility:_cmd]; + return self; +} + +// TESTING; + +- (BOOL) isEmpty +{ + return ([self count] == 0); +} + +// Potentially inefficient, may be overridden in subclasses; +- (BOOL) includesElement: (elt)anElement +{ + int (*cf)(elt,elt) = [self comparisonFunction]; + BOOL test(elt e) + { + if (!((*cf)(anElement, e))) + return YES; + else + return NO; + } + + return [self trueForAnyElementsByCalling:test]; +} + +- (BOOL) isSubsetOf: (id )aCollection +{ + BOOL test(elt e) + { + return [aCollection includesElement:e]; + } + return [self trueForAllElementsByCalling:test]; +} + +- (BOOL) contentsEqual: (id )aCollection +{ + id bag; + BOOL flag; + + // Could use objc_msg_lookup here also; + void doIt(elt e) + { + if ([bag includesElement:e]) + [bag removeElement:e]; + else + flag = NO; + } + + if ([self count] != [aCollection count] + || ([self comparisonFunction] != [aCollection comparisonFunction])) + return NO; + bag = [[Bag alloc] initWithContentsOf:aCollection]; + flag = YES; + [self withElementsCall:doIt whileTrue:&flag]; + if ((!flag) || [bag count]) + flag = NO; + else + flag = YES; + [bag free]; + return flag; +} + +/* This is what I'd like the -compare: implementation in Object.m to + look like. */ +- (int) _objectCompare: anObject +{ + if (self == anObject) + return 0; + if (self > anObject) + return 1; + else + return -1; +} + +// Fix this ; +// How do we want to compare unordered contents?? ; +- (int) compareContentsOf: (id )aCollection +{ + if ([self contentsEqual:aCollection]) + return 0; + if (self > aCollection) + return 1; + return -1; +} + +// Deal with this in IndexedCollection also ; +// How do we want to compare collections? ; +- (int) compare: anObject +{ + if ([self isEqual:anObject]) + return 0; + if (self > anObject) + return 1; + return -1; +} + +- (BOOL) isEqual: anObject +{ + if (self == anObject) + return YES; + if ([anObject class] == [self class] + && [self contentsEqual: anObject] ) + return YES; + else + return NO; +} + +- (BOOL) isDisjointFrom: (id )aCollection +{ + // Use objc_msg_lookup here also; + BOOL flag = YES; + void doIt(elt e) + { + if (![aCollection includesElement:e]) + flag = NO; + } + [self withElementsCall:doIt whileTrue:&flag]; + return !flag; +} + +- (BOOL) trueForAllElementsByCalling: (BOOL(*)(elt))aFunc +{ + BOOL flag = YES; + void doIt(elt e) + { + if (!((*aFunc)(e))) + flag = NO; + } + [self withElementsCall:doIt whileTrue:&flag]; + return flag; +} + +- (BOOL) trueForAllObjectsByCalling: (BOOL(*)(id))aFunc +{ + BOOL flag = YES; + void doIt(elt e) + { + if (!((*aFunc)(e.id_u))) + flag = NO; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt whileTrue:&flag]; + return flag; +} + +- (BOOL) trueForAnyElementsByCalling: (BOOL(*)(elt))aFunc; +{ + BOOL flag = YES; + void doIt(elt e) + { + if ((*aFunc)(e)) + flag = NO; + } + [self withElementsCall:doIt whileTrue:&flag]; + return !flag; +} + +- (BOOL) trueForAnyObjectsByCalling: (BOOL(*)(id))aFunc; +{ + BOOL flag = YES; + void doIt(elt e) + { + if ((*aFunc)(e.id_u)) + flag = NO; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt whileTrue:&flag]; + return !flag; +} + +// Inefficient, so should be overridden in subclasses; +- (unsigned) count +{ + unsigned n = 0; + void doIt(elt e) + { + n++; + } + [self withElementsCall:doIt]; + return n; +} + +- (unsigned) occurrencesOfElement: (elt)anElement +{ + unsigned count = 0; + int (*cf)(elt,elt) = [self comparisonFunction]; + void doIt(elt e) + { + if (!((*cf)(anElement, e))) + count++; + } + [self withElementsCall:doIt]; + return count; +} + +- (unsigned) occurrencesOfObject: anObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self occurrencesOfElement:anObject]; +} + +- (BOOL) contentsAreObjects +{ + return CONTAINS_OBJECTS; +} + +/* The two default implementations below are used by the node collection + objects: the collections whose contents are required to be objects + conforming to some <...Comprising> protocol. */ + +/* some subclasses will have to override this for correctness */ +- (const char *) contentType +{ + /* objects are the default */ + return @encode(id); +} + +/* some subclasses will have to override this for correctness */ +- (int(*)(elt,elt)) comparisonFunction +{ + /* objects are the default */ + return elt_compare_objects; +} + +// ENUMERATING; + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + [self subclassResponsibility:_cmd]; + return NO; +} + +- (void*) newEnumState +{ + return (void*)0; +} + +- freeEnumState: (void**)enumState +{ + *enumState = (void*)0; + return self; +} + +// Getting objects one at a time. Pass *enumState == 0 to start.; +- (BOOL) getNextObject:(id *)anObjectPtr withEnumState: (void**)enumState; +{ + elt o; + + CHECK_CONTAINS_OBJECTS_ERROR(); + if ([self getNextElement:&o withEnumState:enumState]) + { + *anObjectPtr = o.id_u; + return YES; + } + return NO; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag +{ + void *enumState = [self newEnumState]; + elt e; + + while (*flag && [self getNextElement:&e withEnumState:&enumState]) + (*aFunc)(e); + [self freeEnumState:&enumState]; + return self; +} + +- withElementsCall: (void(*)(elt))aFunc +{ + BOOL flag = YES; + return [self withElementsCall:aFunc whileTrue:&flag]; +} + +- safeWithElementsCall: (void(*)(elt))aFunc +{ + id tmp = [[Array alloc] initWithContentsOf:self]; + [tmp withElementsCall:aFunc]; + [tmp free]; + return self; +} + +- safeWithElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag +{ + id tmp = [[Array alloc] initWithContentsOf:self]; + [tmp withElementsCall:aFunc whileTrue:flag]; + [tmp free]; + return self; +} + +// COPYING; + +- allocCopy +{ +#if NeXT_runtime + return object_copy(self, 0); +#else + return object_copy(self); +#endif +} + +// the copy to be filled by -shallowCopyAs: etc... ; +- emptyCopy +{ + // This will copy all instance vars; + // Subclasses will have to change instance vars like Array's _contents_array; + return [self allocCopy]; +} + +// the copy to be filled by -shallowCopyAs: etc... ; +- emptyCopyAs: (id )aCollectionClass +{ + if (aCollectionClass == [self species]) + return [self emptyCopy]; + else + return [[(id)aCollectionClass alloc] + initWithType:[self contentType]]; +} + +- shallowCopy +{ + return [self shallowCopyAs:[self species]]; +} + +- shallowCopyAs: (id )aCollectionClass +{ + id newColl = [self emptyCopyAs:aCollectionClass]; + [newColl addContentsOf:self]; + return newColl; +} + +/* We can avoid the ugly [self safeWithElementsCall:doIt]; + in -deepen with something like this instead. + This fits with a scheme in which we get rid of the -deepen method, an + idea that I like since calling deepen on an object that has not just + been -shallowCopy'ed can cause major memory leakage. */ +- copyAs: (id )aCollectionClass +{ + id newColl = [self emptyCopyAs:aCollectionClass]; + void addCopy(elt e) + { + [newColl addElement:[e.id_u copy]]; + } + if (CONTAINS_OBJECTS) + [self withElementsCall:addCopy]; + else + [newColl addContentsOf:self]; + return newColl; +} + +- copy +{ + return [self copyAs:[self species]]; +} + +// This method shouldn't be necessary any more; +// (Yuck---replaceElement: is inefficient for many subclasses; +// Also, override this in KeyedCollection and IndexedCollection;) +- deepen +{ + // could use objc_msg_lookup here too; + void doIt(elt o) + { + [self replaceElement:o with:[[o.id_u shallowCopy] deepen]]; + } + + [self error:"Collections don't use -deepen. Use -copy instead."]; + if (!CONTAINS_OBJECTS) + return self; + [self safeWithElementsCall:doIt]; + return self; +} + +- species +{ + return [self class]; +} + + +// FILTERED ENUMERATING; + +- withElementsTrueByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc +{ + void doIt(elt e) + { + if ((*testFunc)(e)) + (*destFunc)(e); + } + [self withElementsCall:doIt]; + return self; +} + +- withObjectsTrueByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc +{ + void doIt(elt e) + { + if ((*testFunc)(e.id_u)) + (*destFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +- withElementsFalseByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc +{ + void doIt(elt e) + { + if (!(*testFunc)(e)) + (*destFunc)(e); + } + [self withElementsCall:doIt]; + return self; +} + +- withObjectsFalseByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc +{ + void doIt(elt e) + { + if (!(*testFunc)(e.id_u)) + (*destFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +- withElementsTransformedByCalling: (elt(*)(elt))transFunc + call: (void(*)(elt))destFunc +{ + void doIt(elt e) + { + (*destFunc)((*transFunc)(e)); + } + [self withElementsCall:doIt]; + return self; +} + +- withObjectsTransformedByCalling: (id(*)(id))transFunc + call: (void(*)(id))destFunc +{ + void doIt(elt e) + { + (*destFunc)((*transFunc)(e.id_u)); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + + +// NON-COPYING ENUMERATORS; + +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc + ifNoneCall: (elt(*)(arglist_t))excFunc +{ + BOOL flag = YES; + elt detectedElement; + void doIt(elt e) + { + if ((*aFunc)(e)) { + flag = NO; + detectedElement = e; + } + } + [self withElementsCall:doIt whileTrue:&flag]; + if (flag) + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + else + return detectedElement; +} + +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc +{ + elt err(arglist_t argFrame) + { + return NO_ELEMENT_FOUND_ERROR(); + } + return [self detectElementByCalling:aFunc ifNoneCall:err]; +} + +- (elt) maxElementByCalling: (int(*)(elt,elt))aFunc +{ + elt max; + BOOL firstTime = YES; + void doIt(elt e) + { + if (firstTime) + { + firstTime = NO; + max = e; + } + else + { + if ((*aFunc)(e,max) > 0) + max = e; + } + } + if (![self count]) + NO_ELEMENT_FOUND_ERROR(); + [self withElementsCall:doIt]; + return max; +} + +- (elt) maxElement +{ + return [self maxElementByCalling:COMPARISON_FUNCTION]; +} + +- (elt) minElementByCalling: (int(*)(elt,elt))aFunc +{ + elt min; + BOOL firstTime = YES; + void doIt(elt e) + { + if (firstTime) + { + firstTime = NO; + min = e; + } + else + { + if ((*aFunc)(e,min) < 0) + min = e; + } + } + if (![self count]) + NO_ELEMENT_FOUND_ERROR(); + [self withElementsCall:doIt]; + return min; +} + +- (elt) minElement +{ + return [self minElementByCalling:COMPARISON_FUNCTION]; +} + +- (elt) injectElement: (elt)initialData byCalling: (elt(*)(elt,elt))aFunc +{ + void doIt(elt e) + { + initialData = (*aFunc)(initialData, e); + } + [self withElementsCall:doIt]; + return initialData; +} + +- injectObject: (id)initialObject byCalling: (id(*)(id,id))aFunc +{ + void doIt(elt e) + { + initialObject = (*aFunc)(initialObject, e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return initialObject; +} + + +- maxObjectByCalling: (int(*)(id,id))aFunc +{ + id max; + BOOL firstTime = YES; + void doIt(id e) + { + if (firstTime) + { + firstTime = NO; + max = e; + } + else + { + if ((*aFunc)(e,max) > 0) + max = e; + } + } + CHECK_CONTAINS_OBJECTS_ERROR(); + if (![self count]) + NO_ELEMENT_FOUND_ERROR(); + [self withObjectsCall:doIt]; + return max; +} + +- maxObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self maxElement].id_u; +} + +- minObjectByCalling: (int(*)(id,id))aFunc +{ + id min; + BOOL firstTime = YES; + void doIt(id e) + { + if (firstTime) + { + firstTime = NO; + min = e; + } + else + { + if ((*aFunc)(e,min) < 0) + min = e; + } + } + CHECK_CONTAINS_OBJECTS_ERROR(); + if (![self count]) + NO_ELEMENT_FOUND_ERROR(); + [self withObjectsCall:doIt]; + return min; +} + +- minObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self minElement].id_u; +} + + + +// OBJECT-COMPATIBLE MESSAGE NAMES + +// ADDING; + +- addObject: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self addElement:newObject]; +} + +- addObjectIfAbsent: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self addElementIfAbsent:newObject]; +} + +- addObjectsCount: (unsigned)count, ... +{ + va_list ap; + + CHECK_CONTAINS_OBJECTS_ERROR(); + // could use objc_msg_lookup here also; + va_start(ap, count); + while (count--) + [self addElement:va_arg(ap, id)]; + va_end(ap); + return self; +} + +// REMOVING AND REPLACING; + +- removeObject: oldObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeElement:oldObject].id_u; +} + +- removeObject: oldObject ifAbsentCall: (id(*)(arglist_t))excFunc +{ + elt elt_err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeElement:oldObject ifAbsentCall:elt_err].id_u; +} + +- removeAllOccurrencesOfObject: oldObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeAllOccurrencesOfElement:oldObject]; +} + +- replaceObject: oldObject with: newObject + ifAbsentCall: (id(*)(arglist_t))excFunc +{ + elt elt_err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self replaceElement:oldObject with: newObject + ifAbsentCall:elt_err].id_u; +} + +- replaceObject: oldObject with: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self replaceElement:oldObject with:newObject].id_u; +} + +- replaceAllOccurrencesOfObject: oldObject with: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self replaceAllOccurrencesOfElement:oldObject with:newObject]; +} + +// TESTING; + +- (BOOL) includesObject: anObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self includesElement:anObject]; +} + + +// ENUMERATING + +- withObjectsCall: (void(*)(id))aFunc +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsCall:doIt]; +} + +- safeWithObjectsCall: (void(*)(id))aFunc +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsCall:doIt]; +} + +- withObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsCall:doIt whileTrue:flag]; +} + +- safeWithObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsCall:doIt whileTrue:flag]; +} + +- makeObjectsPerform: (SEL)aSel +{ + void doIt(elt e) + { + [e.id_u perform:aSel]; + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +- safeMakeObjectsPerform: (SEL)aSel +{ + void doIt(elt e) + { + [e.id_u perform:aSel]; + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithElementsCall:doIt]; + return self; +} + +- safeMakeObjectsPerform: (SEL)aSel with: argObject +{ + void doIt(elt e) + { + [e.id_u perform:aSel with:argObject]; + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithElementsCall:doIt]; + return self; +} + +- makeObjectsPerform: (SEL)aSel with: argObject +{ + void doIt(elt e) + { + /* xxx change these to objc runtime functions, + in case object doesn't responds to "perform" methods. */ + [e.id_u perform:aSel with:argObject]; + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +/* xxx What about adding "-askObjectsPerform: (SEL)aSel with: argObject" + that doesn't perform is object doesn't respond to aSel */ + +- withObjectsPerform: (SEL)aSel in: selObject +{ + id (*aSelImp)(id,SEL,id) = (id(*)(id,SEL,id)) + objc_msg_lookup(selObject, aSel); + void doIt(elt e) + { + aSelImp(selObject, aSel, e.id_u); + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +- safeWithObjectsPerform: (SEL)aSel in: selObject +{ + id (*aSelImp)(id,SEL,id) = (id(*)(id,SEL,id)) + objc_msg_lookup(selObject, aSel); + void doIt(elt e) + { + aSelImp(selObject, aSel, e.id_u); + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithElementsCall:doIt]; + return self; +} + +- withObjectsPerform: (SEL)aSel in: selObject with: argObject +{ + id (*aSelImp)(id,SEL,id,id) = (id(*)(id,SEL,id,id)) + objc_msg_lookup(selObject, aSel); + void doIt(elt e) + { + aSelImp(selObject, aSel, e.id_u, argObject); + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withElementsCall:doIt]; + return self; +} + +- safeWithObjectsPerform: (SEL)aSel in: selObject with: argObject +{ + id (*aSelImp)(id,SEL,id,id) = (id(*)(id,SEL,id,id)) + objc_msg_lookup(selObject, aSel); + void doIt(elt e) + { + aSelImp(selObject, aSel, e.id_u, argObject); + } + + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithElementsCall:doIt]; + return self; +} + + +// NON-COPYING ENUMERATORS; + +- detectObjectByCalling: (BOOL(*)(id))aFunc +{ + id err(arglist_t argFrame) + { + return NO_ELEMENT_FOUND_ERROR(); + } + return [self detectObjectByCalling:aFunc ifNoneCall:err]; +} + +- detectObjectByCalling: (BOOL(*)(id))aFunc + ifNoneCall: (id(*)(arglist_t))excFunc +{ + elt err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + BOOL test(elt e) + { + return (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self detectElementByCalling:test ifNoneCall:err].id_u; +} + +// This printing stuff will change when we get Stream objects; + +- printElement: (elt)anElement +{ + elt_fprintf_elt(stdout, [self contentType], anElement); + return self; +} + +- printForDebugger +{ + void doIt(elt e) + { + [self printElement:e]; + printf(" "); + } + [self withElementsCall:doIt]; + printf(" :%s\n", [self name]); + return self; +} + +- _libobjectsMethodNotYetImplemented: (SEL)aSel +{ + [self error:"method %s in libobjects not yet implemented.\n\ +Contact mccallum@gnu.ai.mit.edu (R. Andrew McCallum)\n\ +for info about latest version.", + sel_get_name(aSel)]; + return self; +} + +- (const char *) libobjectsLicense +{ + const char *licenseString = + "Copyright (C) 1993,1994,1994 Free Software Foundation, Inc.\n" + "\n" + "Written by: R. Andrew McCallum \n" + "Date: May 1993\n" + "\n" + "This object is part of the GNU Objective C Class Library.\n" + "\n" + "This library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Library General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2 of the License, or (at your option) any later version.\n" + "\n" + "This library is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "Library General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU Library General Public\n" + "License along with this library; if not, write to the Free\n" + "Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; + return licenseString; +} + +- write: (TypedStream*)aStream +{ + [super write: aStream]; + [self _writeInit:aStream]; + [self _writeContents:aStream]; + return self; +} + +- read: (TypedStream*)aStream +{ + [super read: aStream]; + [self _readInit:aStream]; + [self _readContents:aStream]; + return self; +} + +- (void) encodeWithCoder: (Coder*)aCoder +{ + [self _encodeCollectionWithCoder:aCoder]; + [self _encodeContentsWithCoder:aCoder]; +} + ++ newWithCoder: (Coder*)aCoder +{ + id newCollection = [self _newCollectionWithCoder:aCoder]; + [newCollection _decodeContentsWithCoder:aCoder]; + return newCollection; +} + +@end + + +@implementation Collection (ArchivingHelpers) + +- (void) _encodeCollectionWithCoder: (Coder*) aCoder +{ + [super encodeWithCoder:aCoder]; + // there are no instance vars; + return; +} + ++ _newCollectionWithCoder: (Coder*) aCoder +{ + // there are no instance vars; + return [super newWithCoder:aCoder]; +} + +- _writeInit: (TypedStream*)aStream +{ + // there are no instance vars; + return self; +} + +- _readInit: (TypedStream*)aStream +{ + // there are no instance vars; + return self; +} + +- (void) _encodeContentsWithCoder: (Coder*)aCoder +{ + unsigned int count = [self count]; + const char *encoding = [self contentType]; + void archiveElement(elt e) + { + [aCoder encodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &e) + withName:"Collection element"]; + } + + [aCoder encodeValueOfSimpleType:@encode(unsigned) + at:&count + withName:"Collection element count"]; + [self withElementsCall:archiveElement]; +} + +- (void) _decodeContentsWithCoder: (Coder*)aCoder +{ + unsigned int count, i; + elt newElement; + const char *encoding = [self contentType]; + + [aCoder decodeValueOfSimpleType:@encode(unsigned) + at:&count + withName:NULL]; + for (i = 0; i < count; i++) + { + [aCoder decodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &newElement) + withName:NULL]; + [self addElement:newElement]; + } +} + +- _writeContents: (TypedStream*)aStream +{ + unsigned int count = [self count]; + const char *encoding = [self contentType]; + void archiveElement(elt e) + { + objc_write_type(aStream, encoding, + elt_get_ptr_to_member(encoding, &e)); + } + + objc_write_type(aStream, @encode(unsigned int), &count); + [self withElementsCall:archiveElement]; + return self; +} + +- _readContents: (TypedStream*)aStream +{ + unsigned int count, i; + elt newElement; + const char *encoding = [self contentType]; + + objc_read_type(aStream, @encode(unsigned int), &count); + for (i = 0; i < count; i++) + { + objc_read_type(aStream, encoding, + elt_get_ptr_to_member(encoding, &newElement)); + [self addElement:newElement]; + } + return self; +} + +@end + diff --git a/Source/ConnectedCoder.m b/Source/ConnectedCoder.m new file mode 100644 index 000000000..fe83ad745 --- /dev/null +++ b/Source/ConnectedCoder.m @@ -0,0 +1,303 @@ +/* Implementation of coder object for remote messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PTR2LONG(P) (((char*)(P))-(char*)0) +#define LONG2PTR(L) (((char*)0)+(L)) + +//#define DEFAULT_SIZE 256 +//#define DEFAULT_SIZE 1024 +#define DEFAULT_SIZE 2000 + +static BOOL debug_connected_coder = NO; + +@implementation ConnectedCoder + ++ newEncodingWithConnection: (Connection*)c + sequenceNumber: (int)n + identifier: (int)i +{ + ConnectedCoder *newsp; + char *b; + MemoryStream* ms; + + b = (char*) (*objc_malloc)(DEFAULT_SIZE); + ms = [[MemoryStream alloc] + _initOnMallocBuffer:b + size:DEFAULT_SIZE + eofPosition:0 + prefix:2 + position:0]; + + newsp = [[self alloc] initEncodingOnStream:ms]; + newsp->connection = c; + newsp->sequence_number = n; + newsp->identifier = i; + [newsp encodeValueOfSimpleType:@encode(typeof(newsp->sequence_number)) + at:&(newsp->sequence_number) + withName:"ConnectedCoder sequence number"]; + [newsp encodeValueOfSimpleType:@encode(typeof(newsp->identifier)) + at:&(newsp->identifier) + withName:"ConnectedCoder identifier"]; + return newsp; +} + ++ newDecodingWithConnection: (Connection*)c + timeout: (int) timeout +{ + ConnectedCoder *newsp; + int len; + char *b; + id inPort = [c inPort]; + MemoryStream *ms; + id rp; + unsigned sent_size; + + b = (char*) (*objc_malloc)(DEFAULT_SIZE); + if (!inPort) [self error:"no inPort"]; + len = [inPort + receivePacket:b + length:DEFAULT_SIZE + fromPort:&rp + timeout:timeout]; + if (len < 0) /* timeout */ + { + [self free]; + return nil; + } + + /* xxx We need to do something if DEFAULT_SIZE is too small for this msg. + Change the interface to Port. */ + sent_size = *(unsigned char*)(b+1); + sent_size = (sent_size * 0x100) + *(unsigned char*)(b); + if (sent_size != len) + [self error:"received packet size overflow?\n" + "packet size sent (%d) != packet size received (%d)", + sent_size, len]; + + ms = [[MemoryStream alloc] + _initOnMallocBuffer:b + size:DEFAULT_SIZE + eofPosition:len-2 + prefix:2 + position:0]; + newsp = [[self alloc] initDecodingOnStream:ms]; + newsp->remotePort = rp; + newsp->connection = [Connection newForInPort:inPort + outPort:newsp->remotePort + ancestorConnection:c]; + [newsp decodeValueOfSimpleType:@encode(typeof(newsp->sequence_number)) + at:&(newsp->sequence_number) + withName:NULL]; + [newsp decodeValueOfSimpleType:@encode(typeof(newsp->identifier)) + at:&(newsp->identifier) + withName:NULL]; + + b[len] = '\0'; /* xxx dangerous, but pretty debug output */ + if (debug_connected_coder) + fprintf(stderr, "startDecoding #=%d id=%d: (%s)\n", + newsp->sequence_number, newsp->identifier, b); + return newsp; +} + +- dismiss +{ + if (![self isDecoding]) + { + int buffer_len; + int sent_len; + id ip, op; + char *b; + + ip = [connection inPort]; + if (!ip) [self error:"no inPort"]; + op = [connection outPort]; + if (!op) [self error:"no outPort"]; + buffer_len = [(MemoryStream*)stream streamBufferLength]; + b = [(MemoryStream*)stream streamBuffer]; + /* Put the packet length in the first two bytes */ + b[0] = buffer_len % 0x100; + b[1] = buffer_len / 0x100; + assert(!(buffer_len / 0x10000)); + sent_len = [ip + sendPacket:b + length:buffer_len + toPort:op + timeout:[connection outTimeout]]; + assert(sent_len == buffer_len); + b[sent_len] = '\0'; /* xxx oooo, dangerous. fix this */ + if (debug_connected_coder) + fprintf(stderr, "finishEncoding 0x%x: #=%d i=%d %d/%d (%s)\n", + (unsigned)self, sequence_number, identifier, + buffer_len, sent_len, b); + } + return [self free]; +} + +static elt +exc_return_null(arglist_t f) +{ + return (void*)0; +} + +- (BOOL) _coderHasConstPtrReference: (unsigned)xref +{ + if (is_decoding) + return [[connection _incomingConstPtrs] includesKey:xref]; + else + return [[connection _outgoingConstPtrs] includesKey:xref]; +} + +- (const void*) _coderConstPtrAtReference: (unsigned)xref; +{ + if (is_decoding) + return [[connection _incomingConstPtrs] + elementAtKey:xref + ifAbsentCall:exc_return_null].void_ptr_u; + else + return [[connection _outgoingConstPtrs] + elementAtKey:xref + ifAbsentCall:exc_return_null].void_ptr_u; +} + +- (void) _coderPutConstPtr: (const void*)p atReference: (unsigned)xref +{ + if (is_decoding) + { + assert(![[connection _incomingConstPtrs] includesKey:xref]); + [[connection _incomingConstPtrs] putElement:(void*)p atKey:xref]; + } + else + { + assert(![[connection _outgoingConstPtrs] includesKey:xref]); + [[connection _outgoingConstPtrs] putElement:(void*)p atKey:xref]; + } + return; +} + +#if CONNECTION_WIDE_OBJECT_REFERENCES + +/* We need to think carefully about reference counts, bycopy and + remote objects before we do this. */ + +/* Some notes: + + Is it really more efficient to send "retain" messages across the + wire than to resend the object? + + How is this related to bycopy objects? Yipes. + + Never let a Proxy be free'd completely until the connection does + down? The other connection is assuming we'll keep track of it and + be able to access it simply by the reference number. + + Even if this is unacceptable, and we always have to sent enough info + to be able to recreate the proxy, we still win with the choice of + +encodeObject:withConnectedCoder because we avoid having + to keep around the local proxies. */ + +- (BOOL) _coderHasObjectReference: (unsigned)xref +{ + if (is_decoding) + return [connection includesProxyForTarget:xref]; + else + return [connection includesLocalObject:(id)LONG2PTR(xref)]; +} + +- _coderObjectAtReference: (unsigned)xref; +{ + if (is_decoding) + return [connection proxyForTarget:xref]; + else + return (id)LONG2PTR(xref); +} + +- (void) _coderPutObject: anObj atReference: (unsigned)xref +{ + /* xxx But we need to deal with bycopy's too!!! Not all of the + "anObj"s are Proxies! */ + if (is_decoding) + { + assert([anObj isProxy]); + assert([anObj targetForProxy] == xref); + /* This gets done in Proxy +newForRemote:connection: + [connection addProxy:anObj]; */ + } + else + { + assert(PTR2LONG(anObj) == xref); + [connection addLocalObject:anObj]; + } +} + +#endif /* CONNECTION_WIDE_REFERENCES */ + +- free +{ + /* Anything else? */ + return [super free]; +} + +- (int) identifier +{ + return identifier; +} + +- connection +{ + return connection; +} + +- remotePort +{ + return remotePort; +} + +- (unsigned) sequenceNumber +{ + return sequence_number; +} + +/* This is called by Coder's designated object encoder */ +- (void) _doEncodeObject: anObj +{ + id c = [anObj classForConnectedCoder:self]; + [self encodeClass:c]; + [c encodeObject:anObj withConnectedCoder:self]; +} + +- (void) resetConnectedCoder /* xxx rename resetCoder */ +{ + [self notImplemented:_cmd]; + /* prepare the receiver to do it's stuff again, + save time by doing this instead of free/malloc for each message */ +} + +@end diff --git a/Source/Connection.m b/Source/Connection.m new file mode 100644 index 000000000..1346923cc --- /dev/null +++ b/Source/Connection.m @@ -0,0 +1,1800 @@ +/* Implementation of connection object for remote object messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* RMC == Remote Method Coder, or Remote Method Call. + It's an instance of ConnectedCoder. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +@interface Connection (GettingCoderInterface) +- doReceivedRequestsWithTimeout: (int)to; +- newReceivedReplyRmcWithSequenceNumber: (int)n; +- newSendingRequestRmc; +- newSendingReplyRmcWithSequenceNumber: (int)n; +- (int) _newMsgNumber; +@end + +#define proxiesHashGate refGate +#define sequenceNumberGate refGate + +static inline BOOL class_is_kind_of(CLASS self, CLASS aClassObject) +{ + CLASS class; + + for (class = self; class!=Nil; class = class_get_super_class(class)) + if (class==aClassObject) + return YES; + return NO; +} + +static inline unsigned int +hash_int (cache_ptr cache, const void *key) +{ + return (unsigned)key & cache->mask; +} + +static inline int +compare_ints (const void *k1, const void *k2) +{ + return !(k1 - k2); +} + +static int +type_get_number_of_arguments (const char *type) +{ + int i = 0; + while (*type) + { + type = objc_skip_argspec (type); + i += 1; + } + return i - 1; +} + +static elt +exc_func_return_nil (arglist_t af) { return nil; } + +/* class defaults */ +static id default_port_class; +static id defaultProxyClass; +static id defaultCoderClass; +static int default_in_timeout; +static int default_out_timeout; + +static BOOL debug_connection = NO; + +/* Perhaps this should be a hashtable, keyed by remote port. + But we may also need to include the local port---even though + when receiving the local port is fixed, there may be more than + one registered connection (with different in ports) in the + application. */ +/* We could write -hash and -isEqual implementations for Connection */ +static Array *connectionArray; +static Lock *connectionArrayGate; + +static Dictionary *rootObjectDictionary; +static Lock *rootObjectDictionaryGate; + +/* rmc handling */ +static Queue *receivedRequestRmcQueue; +static Lock *receivedRequestRmcQueueGate; +static Queue *receivedReplyRmcQueue; +static Lock *receivedReplyRmcQueueGate; + +static int messagesReceivedCount; + +@implementation Connection + ++ initialize +{ + connectionArray = [[Array alloc] init]; + connectionArrayGate = [Lock new]; + receivedRequestRmcQueue = [[Queue alloc] init]; + receivedRequestRmcQueueGate = [Lock new]; + receivedReplyRmcQueue = [[Queue alloc] init]; + receivedReplyRmcQueueGate = [Lock new]; + rootObjectDictionary = [[Dictionary alloc] init]; + rootObjectDictionaryGate = [Lock new]; + messagesReceivedCount = 0; + default_port_class = [SocketPort class]; + defaultProxyClass = [Proxy class]; + defaultCoderClass = [ConnectedCoder class]; + default_in_timeout = CONNECTION_DEFAULT_TIMEOUT; + default_out_timeout = CONNECTION_DEFAULT_TIMEOUT; + return self; +} + ++ setDefaultPortClass: aClass +{ + default_port_class = aClass; + return self; +} + ++ setDefaultProxyClass: aClass +{ + defaultProxyClass = aClass; + return self; +} + ++ defaultProxyClass +{ + return defaultProxyClass; +} + ++ setDefaultCoderClass: aClass +{ + defaultCoderClass = aClass; + return self; +} + ++ defaultCoderClass +{ + return defaultCoderClass; +} + ++ (int) defaultOutTimeout +{ + return default_out_timeout; +} + ++ setDefaultOutTimeout: (int)to +{ + default_out_timeout = to; + return self; +} + ++ (int) defaultInTimeout +{ + return default_in_timeout; +} + ++ setDefaultInTimeout: (int)to +{ + default_in_timeout = to; + return self; +} + ++ (int) messagesReceived +{ + return messagesReceivedCount; +} + +/* For encoding and decoding the method arguments, we have to know where + to find things in the "argframe" as returned by __builtin_apply_args. + + For some situations this is obvious just from the selector type + encoding, but structures passed by value cause a problem because some + architectures actually pass these by reference, i.e. use the + structure-value-address mentioned in the gcc/config/_/_.h files. + + These differences are not encoded in the selector types. + + Below is my current guess for which architectures do this. + + I've also been told that some architectures may pass structures with + sizef(structure) > sizeof(void*) by reference, but pass smaller ones by + value. The code doesn't currently handle that case. + */ + +/* Do we need separate _PASSED_BY_REFERENCE and _RETURNED_BY_REFERENCE? */ + +#if (sparc) || (hppa) || (AM29K) +#define CONNECTION_STRUCTURES_PASSED_BY_REFERENCE 1 +#else +#define CONNECTION_STRUCTURES_PASSED_BY_REFERENCE 0 +#endif + +/* Float and double return values are stored at retframe + 8 bytes + by __builtin_return() + + The retframe consists of 16 bytes. The first 4 are used for ints, + longs, chars, etc. The last 8 are used for floats and doubles. + + xxx This is disgusting. I should get this info from the gcc config + machine description files. xxx + */ +#define FLT_AND_DBL_RETFRAME_OFFSET 8 + + +#if 1 +- (retval_t) connectionForward: (Proxy*)object : (SEL)sel : (arglist_t)argframe +{ + ConnectedCoder *op; + + void encoder(int argnum, void *datum, const char *type, int flags) + { +#define ENCODED_ARGNAME "argument value" + switch (*type) + { + case _C_ID: + if (flags & _F_BYCOPY) + [op encodeObjectBycopy:*(id*)datum withName:ENCODED_ARGNAME]; + else + [op encodeObject:*(id*)datum withName:ENCODED_ARGNAME]; + break; + default: + [op encodeValueOfType:type at:datum withName:ENCODED_ARGNAME]; + } + } + + { + BOOL out_parameters; + const char *type; + retval_t retframe; + int seq_num; + + op = [self newSendingRequestRmc]; + seq_num = [op sequenceNumber]; + + /* get the method types from the selector */ +#if NeXT_runtime + [self error: + "sorry, distributed objects does not work with the NeXT runtime"]; + /* type = [object selectorTypeForProxy:sel]; */ +#else + type = sel_get_type(sel); +#endif + assert(type); + assert(*type); + + /* Send the types that we're using, so that the performer knows + exactly what qualifiers we're using. + If all selectors included qualifiers and I could make sel_types_match() + work the way I wanted, we wouldn't need to do this. */ + [op encodeValueOfSimpleType:@encode(char*) + at:&type + withName:"selector type"]; + + /* xxx This doesn't work with proxies and the NeXT runtime because + type may be a method_type from a remote machine with a + different architecture, and its argframe layout specifiers + won't be right for this machine! */ + out_parameters = dissect_method_call(argframe, type, encoder); + [op dismiss]; + + { + ConnectedCoder *ip = nil; + int last_argnum; + + void decoder(int argnum, void *datum, const char *type, int flags) + { + assert(ip != (id)-1); + if (!ip) + ip = [self newReceivedReplyRmcWithSequenceNumber:seq_num]; + [ip decodeValueOfType:type at:datum withName:NULL]; + if (argnum == last_argnum) + { + /* this must be here to avoid trashing alloca'ed retframe */ + [ip dismiss]; + ip = (id)-1; + } + } + + last_argnum = type_get_number_of_arguments(type) - 1; + retframe = dissect_method_return(argframe, type, out_parameters, + decoder); + return retframe; + } + } +} + +#else + +- (retval_t) connectionForward: (SEL)sel : (arglist_t)argframe +{ + id op; + id ip; + retval_t* retframe = NULL; /* NULL just to avoid uninitialized warning */ + const char *type; + const char *tmptype; + unsigned flags; + int retsize; + char *datum; + BOOL out_parameters = NO; + int argnum; /* for debugging */ + char argname[16]; /* for debugging */ + + op = [self newSendingRequestRmc]; + + /* get the method types from the selector */ + type = sel_get_type(sel); + assert(type); + assert(*type); + + /* Send the types that we're using, so that the performer knows + exactly what qualifiers we're using. + If all selectors included qualifiers and I could make sel_types_match() + work the way I wanted, we wouldn't need to do this. */ + [op encodeValueOfSimpleType:@encode(char*) + at:&type + withName:"selector type"]; + + /* encode arguments */ + tmptype = type; + datum = my_method_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_ID); + if (![*(id*)datum isProxy]) + [self error:"Asking connection to forward to a non-Proxy object"]; +#if 0 + if (![*(id*)datum proxyIsRemote]) + [self error:"Asking connection to forward to non-remote Proxy"]; +#endif + if ([*(id*)datum connectionForProxy] != self) + [self error:"Asking connection to forward to a Proxy it doesn't own"]; + [op encodeValueOfType:tmptype + at:datum + withName:"arg1 receiver"]; + datum = my_method_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_SEL); + [op encodeValueOfType:tmptype + at:datum + withName:"arg2 selector"]; + for (datum = my_method_get_next_argument(argframe, &tmptype), argnum=3; + datum; + datum = my_method_get_next_argument(argframe, &tmptype), argnum++) + { + flags = objc_get_type_qualifiers(tmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + sprintf(argname, "arg%d", argnum); /* too expensive? */ + if (*tmptype == _C_ID) + { + if (flags & _F_BYCOPY) + [op encodeObjectBycopy:*(id*)datum withName:argname]; + else + [op encodeObject:*(id*)datum withName:argname]; + } + else if (*tmptype == _C_CHARPTR) + { + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if ((flags & _F_IN) || !(flags & _F_OUT)) + [op encodeValueOfType:tmptype + at:datum + withName:argname]; + } + else if (*tmptype == _C_PTR) + { + tmptype++; + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + [op encodeValueOfType:tmptype + at:*(void**)datum + withName:argname]; + } + else + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + [op encodeValueOfType:tmptype + at:*(void**)datum + withName:argname]; + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + [op encodeValueOfType:tmptype + at:*(void**)datum + withName:argname]; +#else + [op encodeValueOfType:tmptype + at:datum + withName:argname]; +#endif + } + else + { + [op encodeValueOfType:tmptype + at:datum + withName:argname]; + } + } + [op dismiss]; + + /* get return values, if necessary */ + flags = objc_get_type_qualifiers(type); + tmptype = objc_skip_type_qualifiers(type); + /* xxx What happens with method declared "- (oneway) foo: (out int*)ip;" */ + /* xxx What happens with method declared "- (in char *) bar;" */ + /* Is this right? Do we also have to check _F_ONEWAY? */ + if (out_parameters || *tmptype != _C_VOID) + { + ip = [self newReceivedReplyRmcWithSequenceNumber: + [op sequenceNumber]]; + + if (*tmptype != _C_VOID) + { + /* decode return value */ + retsize = objc_sizeof_type(tmptype); + /* xxx We need to test retsize's less than 4 Also note that + if we return structures using a structure-value-address, we + are potentially alloca'ing much more than we need here. */ + /* xxx Find out about returning structures by reference + on non--structure-value-address machines, and potentially + just always alloca(RETFRAME_SIZE == sizeof(void*)*4) */ + retframe = alloca(MAX(retsize, sizeof(void*)*4)); + /* xxx change this to a switch (*tmptype) */ + if (*tmptype == _C_PTR) + { + tmptype++; + /* xxx these two cases are the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + *(void**)retframe = + (*objc_malloc)(objc_sizeof_type(tmptype)); + [ip decodeValueOfType:tmptype + at:*(void**)retframe + withName:NULL]; + } + else + { + *(void**)retframe = + (*objc_malloc)(objc_sizeof_type(tmptype)); + [ip decodeValueOfType:tmptype + at:*(void**)retframe + withName:NULL]; + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* xxx These two cases currently the same */ +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + *(void**)retframe = alloca(objc_sizeof_type(tmptype)); + [ip decodeValueOfType:tmptype + at:*(void**)retframe + withName:NULL]; +#else + *(void**)retframe = alloca(objc_sizeof_type(tmptype)); + [ip decodeValueOfType:tmptype + at:*(void**)retframe + withName:NULL]; +#endif + } + else if (*tmptype == _C_FLT || *tmptype == _C_DBL) + { + [ip decodeValueOfType:tmptype + at:((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET + withName:NULL]; + } + else /* Among other things, _C_CHARPTR is handled here */ + { + /* int typesize; xxx Use retsize instead! */ + /* xxx was: (typesize = objc_sizeof_type(tmptype)) */ + /* Special case BOOL (and other types smaller than int) + because retframe doesn't actually point to the char */ + /* xxx What about structures smaller than int's that + are passed by reference on true structure reference- + passing architectures? */ + /* xxx Is this the right test? Use sizeof(int*) instead? */ + if (retsize < sizeof(void*)) + { + *(void**)retframe = 0; + [ip decodeValueOfType:tmptype + at:((char*)retframe)+sizeof(void*)-retsize + withName:NULL]; + } + else + { + [ip decodeValueOfType:tmptype + at:retframe + withName:NULL]; + } + } + } + + /* decode values returned by reference */ + if (out_parameters) + { + for (datum = my_method_get_next_argument(argframe, &tmptype); + datum; + (datum = my_method_get_next_argument(argframe, &tmptype))) + { + flags = objc_get_type_qualifiers(tmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if (*tmptype == _C_PTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + tmptype++; + /* xxx Note that a (char**) is malloc'ed anew here. + Yucky, or worse than yucky. If the returned string + is smaller than the original, we should just put it + there; if the returned string is bigger, I don't know + what to do. */ + /* xxx These two cases are the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + [ip decodeValueOfType:tmptype + at:*(void**)datum + withName:NULL]; + } + else + { + [ip decodeValueOfType:tmptype + at:*(void**)datum + withName:NULL]; + } + } + /* __builtin_return can't return structures by value */ + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + [ip decodeValueOfType:tmptype + at:datum + withName:NULL]; + } + } + } + + [ip dismiss]; + } + else /* void return value */ + { + retframe = alloca(sizeof(void*)); + } + + return retframe; +} + +#endif /* 1 */ + + +#if 1 +- connectionPerformAndDismissCoder: aRmc +{ + char *forward_type; + id op = nil; + int reply_sequence_number; + int numargs; + + void decoder (int argnum, void *datum, const char *type) + { + [aRmc decodeValueOfType:type + at:datum + withName:NULL]; + /* We need this "dismiss" to happen here and not later so that Coder + "-awake..." methods will get sent before the __builtin_apply! */ + if (argnum == numargs-1) + [aRmc dismiss]; + } + void encoder (int argnum, void *datum, const char *type, int flags) + { +#define ENCODED_RETNAME "return value" + if (op == nil) + op = [self newSendingReplyRmcWithSequenceNumber: + reply_sequence_number]; + switch (*type) + { + case _C_ID: + if (flags & _F_BYCOPY) + [op encodeObjectBycopy:*(id*)datum withName:ENCODED_RETNAME]; + else + [op encodeObject:*(id*)datum withName:ENCODED_RETNAME]; + break; + default: + [op encodeValueOfType:type at:datum withName:ENCODED_RETNAME]; + } + } + + /* Save this for later */ + reply_sequence_number = [aRmc sequenceNumber]; + + /* Get the types that we're using, so that we know + exactly what qualifiers the forwarder used. + If all selectors included qualifiers and I could make sel_types_match() + work the way I wanted, we wouldn't need to do this. */ + [aRmc decodeValueOfSimpleType:@encode(char*) + at:&forward_type + withName:NULL]; + + numargs = type_get_number_of_arguments(forward_type); + + make_method_call(forward_type, decoder, encoder); + [op dismiss]; + + (*objc_free)(forward_type); + return self; +} + +#else + +- connectionPerformAndDismissCoder: aRmc +{ + const char *type, *tmptype; + char *forward_type; + const char *ftmptype; + id object; + SEL selector; + IMP imp; + void *retframe; + arglist_t argframe; + int stack_argsize; + int reg_argsize; + char *datum; + id op; + unsigned flags; + BOOL out_parameters = NO; + int reply_sequence_number; + char argname[16]; /* for debugging with TextCoder */ + int argnum; /* for debugging with TextCoder */ + + /* Save this for later */ + reply_sequence_number = [aRmc sequenceNumber]; + + /* Get the types that we're using, so that we know + exactly what qualifiers the forwarder used. + If all selectors included qualifiers and I could make sel_types_match() + work the way I wanted, we wouldn't need to do this. */ + [aRmc decodeValueOfSimpleType:@encode(char*) + at:&forward_type + withName:NULL]; + + /* get object and selector */ + [aRmc decodeValueOfType:@encode(id) + at:&object + withName:NULL]; + /* @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ + [aRmc decodeValueOfType:":" + at:&selector + withName:NULL]; + assert(selector); + + type = sel_get_type(selector); + assert(type); + + /* Set up argframe */ + stack_argsize = types_get_size_of_stack_arguments(type); + reg_argsize = types_get_size_of_register_arguments(type); + argframe = (arglist_t) alloca(sizeof(char*) + reg_argsize); + if (stack_argsize) + argframe->arg_ptr = alloca(stack_argsize); + else + argframe->arg_ptr = 0; + + /* decode rest of arguments */ + tmptype = type; + ftmptype = objc_skip_argspec(forward_type); + datum = my_method_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_ID); + *(id*)datum = object; + assert(object); + ftmptype = objc_skip_argspec(ftmptype); + datum = my_method_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_SEL); + *(SEL*)datum = selector; + assert(selector); + for (datum = my_method_get_next_argument(argframe, &tmptype), + ftmptype = objc_skip_argspec(ftmptype); + datum; + datum = my_method_get_next_argument(argframe, &tmptype), + ftmptype = objc_skip_argspec(ftmptype)) + { + flags = objc_get_type_qualifiers(ftmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if (*tmptype == _C_CHARPTR) + { + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if ((flags & _F_IN) || !(flags & _F_OUT)) + [aRmc decodeValueOfType:tmptype + at:datum + withName:NULL]; + } + else if (*tmptype == _C_PTR) + { + tmptype++; + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* *(void**)datum = alloca(sizeof(void*)); */ + /* xxx or should this be alloca?! + What about inout params? Where do they get freed? */ + *(void**)datum = + (*objc_malloc)(objc_sizeof_type(tmptype)); + if ((flags & _F_IN) || !(flags & _F_OUT)) + [aRmc decodeValueOfType:tmptype + at:*(void**)datum + withName:NULL]; + } + else + { + /* xxx or should this be alloca?! + What about inout params? Where dothey get freed? */ + *(char**)datum = + (*objc_malloc)(objc_sizeof_type(tmptype)); + if ((flags & _F_IN) || !(flags & _F_OUT)) + [aRmc decodeValueOfType:tmptype + at:*(void**)datum + withName:NULL]; + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + *(void**)datum = alloca(objc_sizeof_type(tmptype)); + [aRmc decodeValueOfType:tmptype + at:*(void**)datum + withName:NULL]; +#else + [aRmc decodeValueOfType:tmptype + at:datum + withName:NULL]; +#endif + } + else + { + [aRmc decodeValueOfType:tmptype + at:datum + withName:NULL]; + } + } + /* We need this "dismiss" to happen here and not later so that Coder + "-awake..." methods will get sent before the __builtin_apply! */ + [aRmc dismiss]; + + /* Call the method */ + imp = objc_msg_lookup(object, selector); + assert(imp); + retframe = __builtin_apply((apply_t)imp, + argframe, + stack_argsize); + + /* Return results, if necessary */ + flags = objc_get_type_qualifiers(forward_type); + ftmptype = objc_skip_type_qualifiers(forward_type); + tmptype = objc_skip_type_qualifiers(type); + /* Is this right? Do we also have to check _F_ONEWAY? */ + if (out_parameters || *tmptype != _C_VOID) + { + op = [self newSendingReplyRmcWithSequenceNumber: + reply_sequence_number]; + +#define ENCODE_RETNAME "return value" + + if (*tmptype != _C_VOID) + { + /* encode return value */ + /* xxx Change this to switch(*tmptype) */ + if (*tmptype == _C_ID) + { + if (flags & _F_BYCOPY) + [op encodeObjectBycopy:*(id*)retframe withName:ENCODE_RETNAME]; + else + [op encodeObject:*(id*)retframe withName:ENCODE_RETNAME]; + } + else if (*tmptype == _C_PTR) + { + tmptype++; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + [op encodeValueOfType:tmptype + at:*(void**)retframe + withName:ENCODE_RETNAME]; + else + [op encodeValueOfType:tmptype + at:*(void**)retframe + withName:ENCODE_RETNAME]; + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* xxx these two cases currently the same? */ +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + [op encodeValueOfType:tmptype + at:*(void**)retframe + withName:ENCODE_RETNAME]; +#else + [op encodeValueOfType:tmptype + at:*(void**)retframe + withName:ENCODE_RETNAME]; +#endif + } + else if (*tmptype == _C_FLT || *tmptype == _C_DBL) + { + [op encodeValueOfType:tmptype + at:((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET + withName:ENCODE_RETNAME]; + } + else /* Among other types, _C_CHARPTR is handled here */ + { + int retsize = objc_sizeof_type(tmptype); + /* Special case BOOL (and other types smaller than int) + because retframe doesn't actually point to the char */ + /* xxx What about structures smaller than int's that + are passed by reference on true structure reference- + passing architectures? */ + /* xxx Is this the right test? Use sizeof(int*) instead? */ + if (retsize < sizeof(void*)) + { + [op encodeValueOfType:tmptype + at:((char*)retframe)+sizeof(void*)-retsize + withName:ENCODE_RETNAME]; + } + else + { + [op encodeValueOfType:tmptype + at:retframe + withName:ENCODE_RETNAME]; + } + } + } + + /* encode values returned by reference */ + if (out_parameters) + { + for (datum = my_method_get_next_argument(argframe,&tmptype), + argnum = 1, + ftmptype = objc_skip_argspec(ftmptype); + datum; + datum = my_method_get_next_argument(argframe,&tmptype), + argnum++, + ftmptype = objc_skip_argspec(ftmptype)) + { + flags = objc_get_type_qualifiers(ftmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + sprintf(argname, "arg%d", argnum); /* too expensive? */ + if ((*tmptype == _C_PTR) + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + tmptype++; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + [op encodeValueOfType:tmptype + at:*(void**)datum + withName:argname]; + } + else + { + [op encodeValueOfType:tmptype + at:*(void**)datum + withName:argname]; + } + } + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + [op encodeValueOfType:tmptype + at:datum + withName:argname]; + } + } + } + [op dismiss]; + } + (*objc_free)(forward_type); + return self; +} +#endif + ++ (id ) allConnections +{ + return [connectionArray copy]; +} + ++ (unsigned) connectionsCount +{ + return [connectionArray count]; +} + ++ (unsigned) connectionsCountWithInPort: (Port*)aPort +{ + unsigned count = 0; + elt e; + [connectionArrayGate lock]; + FOR_ARRAY(connectionArray, e) + { + if ([aPort isEqual:[e.id_u inPort]]) + count++; + } + FOR_ARRAY_END; + [connectionArrayGate unlock]; + return count; +} + +/* This should get called whenever an object free's itself */ ++ removeObject: anObj +{ + id c; + int i, count = [connectionArray count]; + for (i = 0; i < count; i++) + { + c = [connectionArray objectAtIndex:i]; + [c removeLocalObject:anObj]; + [c removeProxy:anObj]; + } + return self; +} + ++ unregisterForInvalidationNotification: anObj +{ + int i, count = [connectionArray count]; + for (i = 0; i < count; i++) + { + [[connectionArray objectAtIndex:i] + unregisterForInvalidationNotification:anObj]; + } + return self; +} + +- init +{ + id newPort = [default_port_class newPort]; + id newConn = + [Connection newForInPort:newPort outPort:nil ancestorConnection:nil]; + [self free]; + return newConn; +} + ++ new +{ + id newPort = [default_port_class newPort]; + id newConn = + [Connection newForInPort:newPort outPort:nil ancestorConnection:nil]; + return newConn; +} + ++ (Connection*) newWithRootObject: anObj; +{ + id newPort; + id newConn; + + newPort = [default_port_class newPort]; + newConn = [self newForInPort:newPort outPort:nil + ancestorConnection:nil]; + [self setRootObject:anObj forInPort:newPort]; + return newConn; +} + +/* I want this method name to clearly indicate that we're not connecting + to a pre-existing registration name, we're registering a new name, + and this method will fail if that name has already been registered. + This is why I don't like "newWithRegisteredName:" --- it's unclear + if we're connecting to another Connection that already registered + with that name. */ + ++ (Connection*) newRegisteringAtName: (const char*)n withRootObject: anObj +{ + id newPort; + id newConn; + + newPort = [default_port_class newRegisteredPortWithName:n]; + newConn = [self newForInPort:newPort outPort:nil + ancestorConnection:nil]; + [self setRootObject:anObj forInPort:newPort]; + return newConn; +} + ++ (Proxy*) rootProxyAtName: (const char*)n; +{ + return [self rootProxyAtName:n onHost:""]; +} + ++ (Proxy*) rootProxyAtName: (const char*)n onHost: (const char*)h; +{ + id p = [default_port_class newPortFromRegisterWithName:n onHost:h]; + return [self rootProxyAtPort:p]; +} + ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort; +{ + id newInPort = [default_port_class newPort]; + return [self rootProxyAtPort: anOutPort withInPort:newInPort]; +} + ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort withInPort: (Port*)anInPort; +{ + Connection *newConn = [self newForInPort:anInPort + outPort:anOutPort + ancestorConnection:nil]; + Proxy *newRemote; + + newRemote = [newConn rootProxy]; + return newRemote; +} + + +- _superInit +{ + [super init]; + return self; +} + +/* This is the designated initializer for Connection */ + ++ (Connection*) newForInPort: (Port*)ip outPort: (Port*)op + ancestorConnection: (Connection*)ancestor; +{ + Connection *newConn; + int i, count; + id newConnInPort, newConnOutPort; + + [connectionArrayGate lock]; + + /* Find previously existing connection if there */ + /* xxx Clean this up */ + count = [connectionArray count]; + for (i = 0; i < count; i++) + { + newConn = [connectionArray objectAtIndex:i]; + newConnInPort = [newConn inPort]; + newConnOutPort = [newConn outPort]; + if ([newConnInPort isEqual:ip] + && [newConnOutPort isEqual:op]) + { + [connectionArrayGate unlock]; + return newConn; + } + } + + newConn = [[Connection alloc] _superInit]; + if (debug_connection) + printf("new connection 0x%x, inPort 0x%x outPort 0x%x\n", + (unsigned)newConn, (unsigned)ip, (unsigned)op); + newConn->in_port = ip; + [ip retain]; + newConn->out_port = op; + [op retain]; + newConn->message_count = 0; + + /* Careful: We might want to use (void*) encoding because we + don't want Dictionary to send -isEqual messages to the proxy's + that are in the Dictionary. YES. */ + newConn->local_targets = [[Dictionary alloc] + initWithType:@encode(id) + keyType:@encode(unsigned)]; + newConn->remote_proxies = [[Dictionary alloc] + initWithType:@encode(void*) + keyType:@encode(unsigned)]; + newConn->incoming_const_ptrs = [[Dictionary alloc] + initWithType:@encode(void*) + keyType:@encode(unsigned)]; + newConn->outgoing_const_ptrs = [[Dictionary alloc] + initWithType:@encode(void*) + keyType:@encode(unsigned)]; + newConn->in_timeout = [self defaultInTimeout]; + newConn->out_timeout = [self defaultOutTimeout]; + newConn->port_class = [ancestor portClass]; + newConn->queue_dialog_interruptions = YES; + newConn->delegate = nil; + + /* Here ask the delegate for permission. */ + /* delegate is responsible for freeing newConn if it returns something + different. */ + if ([[ancestor delegate] respondsTo:@selector(connection:didConnect:)]) + newConn = [[ancestor delegate] connection:ancestor + didConnect:newConn]; + + [ip registerForInvalidationNotification:newConn]; + [op registerForInvalidationNotification:newConn]; + + [connectionArray addObject:newConn]; + [connectionArrayGate unlock]; + + return newConn; +} + +/* This needs locks */ +- (void) dealloc +{ + if (debug_connection) + printf("deallocating 0x%x\n", (unsigned)self); + [self invalidate]; + [connectionArray removeObject:self]; + /* Remove rootObject from rootObjectDictionary if this is last connection */ + if (![Connection connectionsCountWithInPort:in_port]) + [Connection setRootObject:nil forInPort:in_port]; + [in_port unregisterForInvalidationNotification:self]; + [out_port unregisterForInvalidationNotification:self]; + [in_port release]; + [out_port release]; + { + void deallocObj (elt o) + { + [o.id_u dealloc]; + } + [proxiesHashGate lock]; + [remote_proxies withElementsCall:deallocObj]; + [remote_proxies free]; + [local_targets free]; + [incoming_const_ptrs free]; + [outgoing_const_ptrs free]; + [proxiesHashGate unlock]; + } + [super dealloc]; + return; +} + +/* to < 0 will never time out */ +- (void) runConnectionWithTimeout: (int)to +{ + [self doReceivedRequestsWithTimeout:to]; +} + +- (void) runConnection +{ + [self runConnectionWithTimeout:-1]; +} + +- (Proxy*) rootProxy +{ + id op, ip; + Proxy *newProxy; + int seq_num = [self _newMsgNumber]; + + assert(in_port); + op = [[self coderClass] + newEncodingWithConnection:self + sequenceNumber:seq_num + identifier:ROOTPROXY_REQUEST]; + [op dismiss]; + ip = [self newReceivedReplyRmcWithSequenceNumber:seq_num]; + [ip decodeObjectAt:&newProxy withName:NULL]; + assert(class_is_kind_of(newProxy->isa, objc_get_class("Proxy"))); + [ip dismiss]; + return newProxy; +} + +- _sendShutdown +{ + id op; + + assert(in_port); + op = [[self coderClass] + newEncodingWithConnection:self + sequenceNumber:[self _newMsgNumber] + identifier:CONNECTION_SHUTDOWN]; + [op dismiss]; + return self; +} + +- (const char *) _typeForSelector: (SEL)sel remoteTarget: (unsigned)target +{ + id op, ip; + char *type; + int seq_num; + + assert(in_port); + seq_num = [self _newMsgNumber]; + op = [[self coderClass] + newEncodingWithConnection:self + sequenceNumber:seq_num + identifier:METHODTYPE_REQUEST]; + [op encodeValueOfType:":" + at:&sel + withName:NULL]; + [op encodeValueOfSimpleType:@encode(unsigned) + at:&target + withName:NULL]; + [op dismiss]; + ip = [self newReceivedReplyRmcWithSequenceNumber:seq_num]; + [ip decodeValueOfSimpleType:@encode(char*) + at:&type + withName:NULL]; + [ip dismiss]; + return type; +} + +- _handleMethodTypeRequest: rmc +{ + ConnectedCoder* op; + unsigned target; + SEL sel; + const char *type; + struct objc_method* m; + + assert(in_port); + assert([rmc connection] == self); + op = [[self coderClass] + newEncodingWithConnection:[rmc connection] + sequenceNumber:[rmc sequenceNumber] + identifier:METHODTYPE_REPLY]; + + [rmc decodeValueOfType:":" + at:&sel + withName:NULL]; + [rmc decodeValueOfSimpleType:@encode(unsigned) + at:&target + withName:NULL]; + /* xxx We should make sure that TARGET is a valid object. */ + /* Not actually a Proxy, but we avoid the warnings "id" would have made. */ + m = class_get_instance_method(((Proxy*)target)->isa, sel); + /* Perhaps I need to be more careful in the line above to get the + version of the method types that has the type qualifiers in it. + Search the protocols list. */ + if (m) + type = m->method_types; + else + type = ""; + [op encodeValueOfSimpleType:@encode(char*) + at:&type + withName:"Requested Method Type for Target"]; + [op dismiss]; + return self; +} + +- _handleRemoteRootObject: rmc +{ + id rootObject = [Connection rootObjectForInPort:in_port]; + ConnectedCoder* op = [[self coderClass] + newEncodingWithConnection:[rmc connection] + sequenceNumber:[rmc sequenceNumber] + identifier:ROOTPROXY_REPLY]; + assert(in_port); + /* Perhaps we should turn this into a class method. */ + assert([rmc connection] == self); + [op encodeObject:rootObject withName:"root object"]; + [op dismiss]; + return self; +} + +- _newReceivedRmcWithTimeout: (int)to +{ + id rmc; + + rmc = [[self coderClass] newDecodingWithConnection:self + timeout:to]; + /* if (!rmc) [self error:"received timed out"]; */ + assert((!rmc) || [rmc isDecoding]); + return rmc; +} + +- (int) _newMsgNumber +{ + int n; + + [sequenceNumberGate lock]; + n = message_count++; + [sequenceNumberGate unlock]; + return n; +} + +- doReceivedRequestsWithTimeout: (int)to +{ + id rmc; + unsigned count; + + for (;;) + { + if (debug_connection) + printf("%s\n", sel_get_name(_cmd)); + + /* Get a rmc */ + [receivedRequestRmcQueueGate lock]; + count = [receivedRequestRmcQueue count]; + if (count) + { + if (debug_connection) + printf("Getting received request from queue\n"); + rmc = [receivedRequestRmcQueue dequeueObject]; + [receivedRequestRmcQueueGate unlock]; + } + else + { + [receivedRequestRmcQueueGate unlock]; + rmc = [self _newReceivedRmcWithTimeout:to]; + } + + if (!rmc) return self; /* timed out */ + assert([rmc isDecoding]); + + /* Process the rmc */ + switch ([rmc identifier]) + { + case ROOTPROXY_REQUEST: + [[rmc connection] _handleRemoteRootObject:rmc]; + [rmc dismiss]; + break; + case ROOTPROXY_REPLY: + [self error:"Got ROOTPROXY reply when looking for request"]; + break; + case METHOD_REQUEST: + { + assert([rmc isDecoding]); + [[rmc connection] connectionPerformAndDismissCoder:rmc]; + break; + } + case METHOD_REPLY: + /* Will this ever happen? + Yes, with multi-threaded callbacks */ + [receivedReplyRmcQueueGate lock]; + [receivedReplyRmcQueue enqueueObject:rmc]; + [receivedReplyRmcQueueGate unlock]; + break; + case METHODTYPE_REQUEST: + [[rmc connection] _handleMethodTypeRequest:rmc]; + [rmc dismiss]; + break; + case METHODTYPE_REPLY: + /* Will this ever happen? + Yes, with multi-threaded callbacks */ + [receivedReplyRmcQueueGate lock]; + [receivedReplyRmcQueue enqueueObject:rmc]; + [receivedReplyRmcQueueGate unlock]; + break; + case CONNECTION_SHUTDOWN: + { + id c = [rmc connection]; + [c invalidate]; + if (c == self) + [self error:"connection waiting for request was shut down"]; + [c dealloc]; + break; + } + default: + [self error:"unrecognized ConnectedCoder identifier"]; + } + } + return self; /* we never get here */ +} + +- newReceivedReplyRmcWithSequenceNumber: (int)n +{ + id rmc, aRmc; + unsigned count, i; + + again: + + /* Get a rmc */ + rmc = nil; + [receivedReplyRmcQueueGate lock]; + count = [receivedReplyRmcQueue count]; + /* There should be a per-thread queue of rmcs so we can do + callbacks when multi-threaded. */ + for (i = 0; i < count; i++) + { + aRmc = [receivedReplyRmcQueue objectAtIndex:i]; + if ([aRmc connection] == self + && [aRmc sequenceNumber] == n) + { + if (debug_connection) + printf("Getting received reply from queue\n"); + [receivedReplyRmcQueue removeObjectAtIndex:i]; + rmc = aRmc; + break; + } + } + [receivedReplyRmcQueueGate unlock]; + if (rmc == nil) + rmc = [self _newReceivedRmcWithTimeout:in_timeout]; + if (rmc == nil) + { + /* We timed out */ + [self error:"connection timed out after waiting %d milliseconds " + "for a reply", + in_timeout]; + /* Eventually we need to change this from crashing to + connection invalidating? I want to use gcc exceptions for this. */ + } + + /* Process the rmc we got */ + switch ([rmc identifier]) + { + case ROOTPROXY_REQUEST: + [self _handleRemoteRootObject: rmc]; + [rmc dismiss]; + break; + case METHODTYPE_REQUEST: + [self _handleMethodTypeRequest:rmc]; + [rmc dismiss]; + break; + case ROOTPROXY_REPLY: + case METHOD_REPLY: + case METHODTYPE_REPLY: + if ([rmc connection] != self) + { + [receivedReplyRmcQueueGate lock]; + [receivedReplyRmcQueue enqueueObject:rmc]; + [receivedReplyRmcQueueGate unlock]; + } + else + { + if ([rmc sequenceNumber] != n) + [self error:"sequence number mismatch %d != %d\n", + [rmc sequenceNumber], n]; + if (debug_connection) + printf("received reply number %d\n", n); + return rmc; + } + break; + case METHOD_REQUEST: + /* + While waiting for a reply, + we can either honor new requests from other connections immediately, + or just queue them. */ + if (queue_dialog_interruptions && [rmc connection] != self) + { + /* Here we queue them */ + [receivedRequestRmcQueueGate lock]; + [receivedRequestRmcQueue enqueueObject:rmc]; + [receivedRequestRmcQueueGate unlock]; + } + else + { + /* Here we honor them right away */ + [self connectionPerformAndDismissCoder:rmc]; + } + break; + case CONNECTION_SHUTDOWN: + { + id c = [rmc connection]; + [c invalidate]; + if (c == self) + [self error:"connection waiting for reply was shut down"]; + [c dealloc]; + [rmc dismiss]; + break; + } + default: + [self error:"unrecognized ConnectedCoder identifier"]; + } + goto again; + + return rmc; +} + +- newSendingRequestRmc +{ + id rmc; + + assert(in_port); + rmc = [[self coderClass] newEncodingWithConnection:self + sequenceNumber:[self _newMsgNumber] + identifier:METHOD_REQUEST]; + return rmc; +} + +- newSendingReplyRmcWithSequenceNumber: (int)n +{ + id rmc = [[self coderClass] + newEncodingWithConnection:self + sequenceNumber:n + identifier:METHOD_REPLY]; + return rmc; +} + +- removeLocalObject: anObj +{ + unsigned target = PTR2LONG(anObj); + [proxiesHashGate lock]; + if ([local_targets includesKey:target]) + { + [local_targets removeElementAtKey:target]; + [anObj release]; + } + [proxiesHashGate unlock]; + return self; +} + +- removeProxy: (Proxy*)aProxy +{ + unsigned target = [aProxy targetForProxy]; + [proxiesHashGate lock]; + if ([remote_proxies includesKey:target]) + [remote_proxies removeElementAtKey:target]; + [proxiesHashGate unlock]; + return self; +} + +- (id ) localObjects +{ + id l = [Array alloc]; + + [proxiesHashGate lock]; + [l initWithContentsOf:local_targets]; + [proxiesHashGate unlock]; + return l; +} + +- (id ) proxies +{ + id a = [[Array alloc] initWithCapacity:[remote_proxies count]]; + void doit (elt e) + { + [a appendElement:e]; + } + + [proxiesHashGate lock]; + [remote_proxies withElementsCall:doit]; + [proxiesHashGate unlock]; + return a; +} + +- (Proxy*) proxyForTarget: (unsigned)target +{ + Proxy *p; + [proxiesHashGate lock]; + if ([remote_proxies includesKey:target]) + p = [remote_proxies elementAtKey:target].id_u; + else + p = nil; + [proxiesHashGate unlock]; + assert(!p || [p connectionForProxy] == self); + return p; +} + +- addProxy: (Proxy*) aProxy +{ + unsigned target = [aProxy targetForProxy]; + assert(aProxy->isa == [Proxy class]); + assert([aProxy connectionForProxy] == self); + [proxiesHashGate lock]; + if ([remote_proxies includesKey:target]) + [self error:"Trying to add the same proxy twice"]; + [remote_proxies putElement:aProxy atKey:target]; + [proxiesHashGate unlock]; + return self; +} + +- (BOOL) includesProxyForTarget: (unsigned)target +{ + BOOL ret; + [proxiesHashGate lock]; + ret = [remote_proxies includesKey:target]; + [proxiesHashGate unlock]; + return ret; +} + +- (BOOL) includesLocalObject: anObj +{ + unsigned target = PTR2LONG(anObj); + BOOL ret; + [proxiesHashGate lock]; + ret = [local_targets includesKey:target]; + [proxiesHashGate unlock]; + return ret; +} + +- addLocalObject: anObj +{ + unsigned target = PTR2LONG(anObj); + [proxiesHashGate lock]; + if (![local_targets includesKey:target]) + { + [anObj retain]; + [local_targets putElement:anObj atKey:target]; + } + [proxiesHashGate unlock]; + return self; +} + +/* Pass nil to remove any reference keyed by aPort. */ ++ setRootObject: anObj forInPort: (Port*)aPort +{ + id oldRootObject = [self rootObjectForInPort:aPort]; + + if (oldRootObject != anObj) + { + if (anObj) + { + [anObj retain]; + [rootObjectDictionaryGate lock]; + [rootObjectDictionary putElement:anObj atKey:aPort]; + [rootObjectDictionaryGate unlock]; + } + else /* anObj == nil && oldRootObject != nil */ + { + [rootObjectDictionaryGate lock]; + [rootObjectDictionary removeElementAtKey:aPort]; + [rootObjectDictionaryGate unlock]; + } + [oldRootObject release]; + } + return self; +} + ++ rootObjectForInPort: (Port*)aPort +{ + id ro; + [rootObjectDictionaryGate lock]; + ro = [rootObjectDictionary elementAtKey:aPort + ifAbsentCall:exc_func_return_nil].id_u; + [rootObjectDictionaryGate unlock]; + return ro; +} + +- setRootObject: anObj +{ + [Connection setRootObject:anObj forInPort:in_port]; + return self; +} + +- rootObject +{ + return [Connection rootObjectForInPort:in_port]; +} + +- (int) outTimeout +{ + return out_timeout; +} + +- (int) inTimeout +{ + return in_timeout; +} + +- setOutTimeout: (int)to +{ + out_timeout = to; + return self; +} + +- setInTimeout: (int)to +{ + in_timeout = to; + return self; +} + +- portClass +{ + return port_class; +} + +- setPortClass: aPortClass +{ + port_class = aPortClass; + return self; +} + +- proxyClass +{ + /* we might replace this with a per-Connection proxy class. */ + return defaultProxyClass; +} + +- coderClass +{ + /* we might replace this with a per-Connection proxy class. */ + return defaultCoderClass; +} + +- (Port *) outPort +{ + return out_port; +} + +- (Port *) inPort +{ + return in_port; +} + +- delegate +{ + return delegate; +} + +- setDelegate: anObj +{ + delegate = anObj; + return self; +} + +- _incomingConstPtrs +{ + return incoming_const_ptrs; +} + +- _outgoingConstPtrs +{ + return outgoing_const_ptrs; +} + +- senderIsInvalid: anObj +{ + if (anObj == in_port || anObj == out_port) + [self invalidate]; + /* xxx What else? */ + return self; +} + +/* xxx This needs locks */ +- invalidate +{ + if (!isValid) + return nil; + /* xxx Note: this is causing us to send a shutdown message + to the connection that shut *us* down. Don't do that. + Well, perhaps it's a good idea just in case other side didn't really + send us the shutdown; this way we let them know we're going away */ + [self _sendShutdown]; + [super invalidate]; + return self; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self shouldNotImplement:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder; +{ + [self shouldNotImplement:_cmd]; + return self; +} + + +@end + + +#if 0 /* temporarily moved to Coder.m */ + +@implementation Object (ConnectionRequests) + +/* By default, Object's encode themselves as proxies across Connection's */ +- classForConnectedCoder:aRmc +{ + return [[aRmc connection] proxyClass]; +} + +/* But if any object overrides the above method to return [Object class] + instead, the Object implementation of the coding method will actually + encode the object itself, not a proxy */ ++ (void) encodeObject: anObject withConnectedCoder: aRmc +{ + [anObject encodeWithCoder:aRmc]; +} + +@end + +@implementation Object (Retaining) + +- (id) retain +{ + return self; +} + +- (oneway void) release +{ + /* Do nothing */ +} + +- (void) dealloc +{ + /* Do nothing */ +} + +- (unsigned) retainCount +{ + return 0; +} + +@end + +#endif /* 0 temporarily moved to Coder.m */ diff --git a/Source/DelegatePool.m b/Source/DelegatePool.m new file mode 100644 index 000000000..42e655dc3 --- /dev/null +++ b/Source/DelegatePool.m @@ -0,0 +1,190 @@ +/* Implementation of Objective-C "collection of delegates" object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective-C Collection 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +@implementation DelegatePool + ++ initialize +{ + return self; +} + ++ alloc +{ + return (id)class_create_instance(self); +} + ++ new +{ + return [[self alloc] init]; +} + +- init +{ + _list = [[Array alloc] init]; + _send_behavior = SEND_TO_ALL; + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [anEncoder encodeValueOfSimpleType:@encode(unsigned char) + at:&_send_behavior + withName:"DelegatePool Send Behavior"]; + [anEncoder encodeObject:_list + withName:"DelegatePool Collection of Delegates"]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + DelegatePool *n = class_create_instance(self); + [aDecoder decodeValueOfSimpleType:@encode(unsigned char) + at:&(n->_send_behavior) + withName:NULL]; + [aDecoder decodeObjectAt:&(n->_list) + withName:NULL]; + return n; +} + + +- write: (TypedStream*)aStream +{ + objc_write_type(aStream, @encode(unsigned char), &_send_behavior); + objc_write_object(aStream, _list); + return self; +} + +- read: (TypedStream*)aStream +{ + objc_write_type(aStream, @encode(unsigned char), &_send_behavior); + objc_read_object(aStream, &_list); + return self; +} + + +- free +{ + [_list free]; +#if NeXT_runtime + return (id) object_dispose((Object*)self); +#else + return (id) object_dispose(self); +#endif +} + + +// MANIPULATING COLLECTION OF DELEGATES; + +- delegatePoolAddObject: anObject +{ + [_list addObject: anObject]; + return self; +} + +- delegatePoolAddObjectIfAbsent: anObject +{ + [_list addObjectIfAbsent: anObject]; + return self; +} + +- delegatePoolRemoveObject: anObject +{ + return [_list removeObject:anObject]; +} + +- (BOOL) delegatePoolIncludesObject: anObject +{ + return [_list includesObject:anObject]; +} + +- delegatePoolCollection +{ + return _list; +} + +- (unsigned char) delegatePoolSendBehavior +{ + return _send_behavior; +} + +- delegatePoolSetSendBehavior: (unsigned char)b +{ + _send_behavior = b; + return self; +} + + +// FOR PASSING ALL OTHER MESSAGES TO DELEGATES; + +- forward: (SEL)aSel :(arglist_t)argFrame +{ + void *ret = 0; + elt delegate; + + switch (_send_behavior) + { + case SEND_TO_ALL: + FOR_ARRAY(_list, delegate) + { + if ([delegate.id_u respondsTo:aSel]) + ret = [delegate.id_u performv:aSel :argFrame]; + } + FOR_ARRAY_END; + break; + + case SEND_TO_FIRST_RESPONDER: + FOR_ARRAY(_list, delegate) + { + if ([delegate.id_u respondsTo:aSel]) + return [delegate.id_u performv:aSel :argFrame]; + } + FOR_ARRAY_END; + break; + + case SEND_UNTIL_YES: + FOR_ARRAY(_list, delegate) + { + if ([delegate.id_u respondsTo:aSel]) + if ((ret = [delegate.id_u performv:aSel :argFrame])) + return ret; + } + FOR_ARRAY_END; + break; + + case SEND_UNTIL_NO: + FOR_ARRAY(_list, delegate) + { + if ([delegate.id_u respondsTo:aSel]) + if (!(ret = [delegate.id_u performv:aSel :argFrame])) + return ret; + } + FOR_ARRAY_END; + break; + } + return ret; +} + +@end diff --git a/Source/Dictionary.m b/Source/Dictionary.m new file mode 100644 index 000000000..b75f08bdc --- /dev/null +++ b/Source/Dictionary.m @@ -0,0 +1,299 @@ +/* Implementation for Objective-C Dictionary collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#define DEFAULT_DICTIONARY_CAPACITY 32 + +@implementation Dictionary + ++ initialize +{ + if (self == [Dictionary class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// MANAGING CAPACITY; + +/* Eventually we will want to have better capacity management, + potentially keep default capacity as a class variable. */ + ++ (unsigned) defaultCapacity +{ + return DEFAULT_DICTIONARY_CAPACITY; +} + +// INITIALIZING; + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding + keyType: (const char *)keyEncoding + capacity: (unsigned)aCapacity +{ + [super initWithType:contentEncoding + keyType:keyEncoding]; + _contents_hash = + coll_hash_new(POWER_OF_TWO(aCapacity), + elt_get_hash_function(keyEncoding), + elt_get_comparison_function(keyEncoding)); + _comparison_function = elt_get_comparison_function(contentEncoding); + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- _writeInit: (TypedStream*)aStream +{ + const char *ce = [self contentType]; + const char *ke = [self keyType]; + + [super _writeInit:aStream]; + /* This implicitly archives the key's comparison and hash functions */ + objc_write_type(aStream, @encode(char*), &ke); + objc_write_type(aStream, @encode(unsigned int), &(_contents_hash->size)); + /* This implicitly archives the content's comparison function */ + objc_write_type(aStream, @encode(char*), &ce); + return self; +} + +- _readInit: (TypedStream*)aStream +{ + char *keyEncoding, *contentEncoding; + unsigned int size; + + [super _readInit:aStream]; + objc_read_type(aStream, @encode(char*), &keyEncoding); + objc_read_type(aStream, @encode(unsigned int), &size); + _contents_hash = + coll_hash_new(size, + elt_get_hash_function(keyEncoding), + elt_get_comparison_function(keyEncoding)); + objc_read_type(aStream, @encode(char*), &contentEncoding); + _comparison_function = elt_get_comparison_function(contentEncoding); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ + +- emptyCopy +{ + Dictionary *copy = [super emptyCopy]; + copy->_contents_hash = + coll_hash_new(_contents_hash->size, + _contents_hash->hash_func, + _contents_hash->compare_func); + return copy; +} + +/* To make sure that former KeyedCollection init'ers go through + Dictionary init, we override the designated initializer for + KeyedCollection. */ +- initWithType: (const char *)contentEncoding + keyType: (const char *)keyEncoding +{ + return [self initWithType:contentEncoding + keyType:keyEncoding + capacity:[[self class] defaultCapacity]]; +} + +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity +{ + return [self initWithType:contentEncoding + keyType:@encode(id) + capacity:aCapacity]; +} + +- initWithCapacity: (unsigned)aCapacity +{ + return [self initWithType:@encode(id) + capacity:aCapacity]; +} + +- free +{ + coll_hash_delete(_contents_hash); + return [super free]; +} + +- freeObjects +{ + if (CONTAINS_OBJECTS) + { + [self makeObjectsPerform:@selector(free)]; + [self empty]; + } + else + [self empty]; + return self; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + coll_hash_empty(_contents_hash); + return self; +} + + +// ADDING OR REPLACING; + +- addElement: (elt)anElement +{ + return [self shouldNotImplement:_cmd]; + /* or should I make up some default behavior here? + Base it on object conforming to protocol, perhaps */ +} + +- putElement: (elt)newContentElement atKey: (elt)aKey +{ + coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey); + if (node) + node->value = newContentElement; + else + coll_hash_add(&_contents_hash, aKey, + newContentElement); + return self; +} + + +// REMOVING; + +- (elt) removeElementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey); + elt ret; + + if (node) + { + ret = node->value; + coll_hash_remove(_contents_hash, aKey); + return ret; + } + else + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); +} + +- (elt) removeElement: (elt)oldElement ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + elt err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + elt key = [self keyElementOfElement:oldElement ifAbsentCall:err]; + return [self removeElementAtKey:key]; +} + + +// GETTING ELEMENTS; + +- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey); + if (node) + return node->value; + else + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); +} + + + +// TESTING; + +- (int(*)(elt,elt)) comparisonFunction +{ + return _comparison_function; +} + +- (const char *) contentType +{ + return elt_get_encoding(_comparison_function); +} + +- (const char *) keyType +{ + return elt_get_encoding(_contents_hash->compare_func); +} + +- (BOOL) includesKey: (elt)aKey +{ + if (coll_hash_node_for_key(_contents_hash, aKey)) + return YES; + else + return NO; +} + +// ENUMERATIONS; + +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState +{ + coll_node_ptr node = coll_hash_next(_contents_hash, enumState); + if (node) + { + *aKeyPtr = node->key; + *anElementPtr = node->value; + return YES; + } + return NO; +} + +- (void*) newEnumState +{ + return (void*)0; +} + +- freeEnumState: (void**)enumState +{ + if (*enumState) + OBJC_FREE(*enumState); + return self; +} + + +- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc + whileTrue: (BOOL *)flag +{ + void *state = 0; + coll_node_ptr node = 0; + + while (flag && (node = coll_hash_next(_contents_hash, &state))) + (*aFunc)(node->key, node->value); + return self; +} + + +@end diff --git a/Source/EltNodeCollector.m b/Source/EltNodeCollector.m new file mode 100644 index 000000000..c17931fc0 --- /dev/null +++ b/Source/EltNodeCollector.m @@ -0,0 +1,466 @@ +/* Implementation for Objective-C EltNodeCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is class works in conjunction with all classes that require + content objects conforming to some <...Comprising> protocol + i.e. LinkedList, BinaryTree, RBTree, etc. + It provides a interface for holding non-object elt's. +*/ + +/* I should override a few more methods to increase efficiency. */ + +#include +#include +#include +#include + +#define DEFAULT_ELT_NODE_CLASS LinkedListEltNode +#define DEFAULT_NODE_COLLECTOR_CLASS LinkedList + +@implementation EltNodeCollector + ++ initialize +{ + if (self == [EltNodeCollector class]) + [self setVersion:0]; /* beta release */ + return self; +} + ++ defaultEltNodeClass +{ + return [DEFAULT_ELT_NODE_CLASS class]; +} + ++ defaultNodeCollectorClass +{ + return [DEFAULT_NODE_COLLECTOR_CLASS class]; +} + +// INITIALIZING AND FREEING; + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding + nodeCollector: aCollector + nodeClass: aNodeClass +{ + [super initWithType:contentEncoding]; + _comparison_function = elt_get_comparison_function(contentEncoding); + // This actually checks that instances conformTo: ??? ; + /* + if (![aNodeClass conformsTo:@protocol(EltHolding)]) + [self error:"in %s, 2nd arg, %s, does not conform to @protocol(%s)", + sel_get_name(_cmd), [nodeClass name], [@protocol(EltHolding) name]]; + */ + _node_class = aNodeClass; + /* We could check to make sure that any objects already in aCollector + conform to @protocol(EltHolding) and that their encoding matches + contentEncoding. */ + _contents_collector = aCollector; + return self; +} + +// remove this; +/* +- initWithType: (const char *)contentEncoding + nodeClass: aNodeClass +{ + return [self initWithType:contentEncoding + nodeCollector:[[[_node_class nodeCollectorClass] alloc] init] + nodeClass:aNodeClass]; +} +*/ + +/* Archiving must mimic the above designated initializer */ + +- (void) _encodeCollectionWithCoder: (Coder*)aCoder +{ + const char *encoding = [self contentType]; + + [super _encodeCollectionWithCoder:aCoder]; + [aCoder encodeValueOfType:@encode(char*) at:&encoding + withName:"EltNodeCollector Content Type Encoding"]; + [aCoder encodeValueOfType:"#" at:&_node_class + withName:"EltNodeCollector Content Node Class"]; +} + ++ _newCollectionWithCoder: (Coder*) aCoder +{ + EltNodeCollector *n; + char *encoding; + + n = [super _newCollectionWithCoder:aCoder]; + [aCoder decodeValueOfType:@encode(char*) at:&encoding withName:NULL]; + n->_comparison_function = elt_get_comparison_function(encoding); + [aCoder decodeValueOfType:"#" at:&(n->_node_class) withName:NULL]; + n->_contents_collector = nil; + return n; +} + +- (void) _encodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder encodeObject:_contents_collector + withName:"EltNodeCollector Contents Collector"]; +} + +- (void) _decodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder decodeObjectAt:&_contents_collector withName:NULL]; +} + +/* Old-style archiving */ + +- _writeInit: (TypedStream*)aStream +{ + const char *encoding = [self contentType]; + + [super _writeInit:aStream]; + objc_write_type(aStream, @encode(char*), &encoding); + objc_write_type(aStream, "#", &_node_class); + return self; +} + +- _readInit: (TypedStream*)aStream +{ + char *encoding; + + [super _readInit:aStream]; + objc_read_type(aStream, @encode(char*), &encoding); + _comparison_function = elt_get_comparison_function(encoding); + objc_read_type(aStream, "#", &_node_class); + _contents_collector = nil; /* taken care of in _readContents: */ + return self; +} + +- _writeContents: (TypedStream*)aStream +{ + objc_write_object(aStream, _contents_collector); + return self; +} + +- _readContents: (TypedStream*)aStream +{ + objc_read_object(aStream, &_contents_collector); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + EltNodeCollector *copy = [super emptyCopy]; + copy->_contents_collector = [_contents_collector emptyCopy]; + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + [_contents_collector empty]; + return self; +} + +/* Override designated initializer for superclass */ +- initWithType: (const char *)contentEncoding +{ + return [self initWithType:contentEncoding + nodeCollector:[[self class] defaultNodeCollectorClass] + nodeClass:[[self class] defaultEltNodeClass]]; +} + +- free +{ + [[_contents_collector freeObjects] free]; + return [super free]; +} + + +// DETERMINING CLASS OF AUTOCREATED NODES; +- eltNodeClass +{ + return _node_class; +} + +// GETTING THE UNDERLYING COLLECTOR; +- contentsCollector +{ + return _contents_collector; +} + +// ADDING; + +- makeEltNodeWithElement: (elt)newElement +{ + return [[[self eltNodeClass] alloc] + initElement:newElement + encoding:[self contentType]]; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + unsigned count = [_contents_collector count]; + CHECK_INDEX_RANGE_ERROR(index, count+1); + if (index == count) + [_contents_collector + appendElement:[self makeEltNodeWithElement:newElement]]; + else + [_contents_collector + insertElement:[self makeEltNodeWithElement:newElement] + before:[_contents_collector elementAtIndex:index]]; + return self; +} + +- insertElement: (elt)newElement before: (elt)oldElement +{ + id node = [self eltNodeWithElement:oldElement]; + if (!node) + ELEMENT_NOT_FOUND_ERROR(oldElement); + [_contents_collector + insertElement:[self makeEltNodeWithElement:newElement] + before:node]; + return self; +} + +- insertElement: (elt)newElement after: (elt)oldElement +{ + id node = [self eltNodeWithElement:oldElement]; + if (!node) + ELEMENT_NOT_FOUND_ERROR(oldElement); + [_contents_collector + insertElement:[self makeEltNodeWithElement:newElement] + after:node]; + return self; +} + +- appendElement: (elt)newElement +{ + [_contents_collector + appendElement:[self makeEltNodeWithElement:newElement]]; + return self; +} + +- prependElement: (elt)newElement +{ + [_contents_collector + prependElement:[self makeEltNodeWithElement:newElement]]; + return self; +} + +- addElement: (elt)newElement +{ + [_contents_collector + addElement:[self makeEltNodeWithElement:newElement]]; + return self; +} + +// REMOVING SWAPING AND REPLACING; + +- swapAtIndeces: (unsigned)index1 : (unsigned)index2; +{ + CHECK_INDEX_RANGE_ERROR(index1, [_contents_collector count]); + CHECK_INDEX_RANGE_ERROR(index2, [_contents_collector count]); + [_contents_collector + swapAtIndeces:index1 :index2]; + return self; +} + +- (elt) removeElementAtIndex: (unsigned)index +{ + id node; + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, [_contents_collector count]); + node = [_contents_collector removeElementAtIndex:index].id_u; + ret = [node elementData]; + [node free]; + return ret; +} + +- (elt) removeElement: (elt)oldElement +{ + id aNode = [self eltNodeWithElement:oldElement]; + elt ret; + + if (!aNode) + return ELEMENT_NOT_FOUND_ERROR(oldElement); + ret = [aNode elementData]; + [_contents_collector removeElement:aNode]; + [aNode free]; + return ret; +} + +- (elt) removeFirstElement +{ + id aNode = [_contents_collector firstElement].id_u; + elt ret; + + if (!aNode) + return NO_ELEMENT_FOUND_ERROR(); + ret = [aNode elementData]; + [_contents_collector removeElement:aNode]; + [aNode free]; + return ret; +} + +- (elt) removeLastElement +{ + id aNode = [_contents_collector lastElement].id_u; + elt ret; + + if (!aNode) + return NO_ELEMENT_FOUND_ERROR(); + ret = [aNode elementData]; + [_contents_collector removeElement:aNode]; + [aNode free]; + return ret; +} + +- (elt) replaceElement: (elt)oldElement with: (elt)newElement +{ + id aNode = [self eltNodeWithElement:oldElement]; + elt ret; + + if (!aNode) + return ELEMENT_NOT_FOUND_ERROR(oldElement); + ret = [aNode elementData]; + [_contents_collector replaceElement:aNode + with:[self makeEltNodeWithElement:newElement]]; + [aNode free]; + return ret; +} + +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement +{ + elt ret; + elt oldNode; + + CHECK_INDEX_RANGE_ERROR(index, [_contents_collector count]); + oldNode = [_contents_collector + replaceElementAtIndex:index + with:[self makeEltNodeWithElement:newElement]]; + ret = [oldNode.id_u elementData]; + [oldNode.id_u free]; + return ret; +} + +// GETTING ELEMENTS BY INDEX; + +- (elt) elementAtIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, [_contents_collector count]); + return [[_contents_collector elementAtIndex:index].id_u elementData]; +} + +// TESTING; + +- eltNodeWithElement: (elt)anElement +{ + int (*cf)(elt,elt) = [self comparisonFunction]; + elt err_ret; + elt err(arglist_t argFrame) + { + return err_ret; + } + BOOL test(elt node) + { + if (!((*cf)([node.id_u elementData], anElement))) + return YES; + else + return NO; + } + err_ret.id_u = nil; + return [_contents_collector detectElementByCalling:test + ifNoneCall:err].id_u; +} + +- (unsigned) count +{ + return [_contents_collector count]; +} + + +// ENUMERATING; + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + elt node; + BOOL flag; + + flag = [_contents_collector getNextElement:&node withEnumState:enumState]; + if (flag) + *anElementPtr = [node.id_u elementData]; + return flag; +} + +- (void*) newEnumState +{ + return [_contents_collector newEnumState]; +} + +- freeEnumState: (void**)enumState +{ + [_contents_collector freeEnumState:enumState]; + return self; +} + +- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + elt node; + BOOL flag; + + flag = [_contents_collector getPrevElement:&node withEnumState:enumState]; + if (flag) + *anElementPtr = [node.id_u elementData]; + return flag; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt node) + { + (*aFunc)([node.id_u elementData]); + } + [_contents_collector withElementsCall:doIt whileTrue:flag]; + return self; +} + +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt node) + { + (*aFunc)([node.id_u elementData]); + } + [_contents_collector withElementsInReverseCall:doIt whileTrue:flag]; + return self; +} + +- (const char *) contentType +{ + return elt_get_encoding(_comparison_function); +} + +- (int(*)(elt,elt)) comparisonFunction +{ + return _comparison_function; +} + +@end + diff --git a/Source/GapArray.m b/Source/GapArray.m new file mode 100644 index 000000000..0bd77f079 --- /dev/null +++ b/Source/GapArray.m @@ -0,0 +1,196 @@ +/* Implementation for Objective-C GapArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include +#include + +@implementation GapArray + ++ initialize +{ + if (self == [GapArray class]) + [self setVersion:0]; /* beta release */ + return self; +} + +/* This is the designated initializer of this class */ +/* Override designated initializer of superclass */ +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity +{ + [super initWithType:contentEncoding + capacity:aCapacity]; + _gap_start = 0; + _gap_size = aCapacity; + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- _readInit: (TypedStream*)aStream +{ + [super _readInit: aStream]; + _gap_start = 0; + _gap_size = _capacity; + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ + +- emptyCopy +{ + GapArray *copy = [super emptyCopy]; + copy->_gap_start = 0; + copy->_gap_size = copy->_capacity; + return copy; +} + +- empty +{ + [super empty]; + _gap_start = 0; + _gap_size = _capacity; + return self; +} + +- setCapacity: (unsigned)newCapacity +{ + if (newCapacity > _count) + { + gapMoveGapTo (self, _capacity-_gap_size); /* move gap to end */ + [super setCapacity: newCapacity]; /* resize */ + _gap_size = _capacity - _gap_start; + } + return self; +} + +- (elt) removeElementAtIndex: (unsigned)index +{ + elt res; + + CHECK_INDEX_RANGE_ERROR(index, _count); + res = _contents_array[GAP_TO_BASIC (index)]; + gapFillHoleAt (self, index); + decrementCount(self); + return res; +} + +- (elt) removeFirstElement +{ + elt res = _contents_array[GAP_TO_BASIC (0)]; + gapFillHoleAt (self, 0); + decrementCount(self); + return res; +} + +- (elt) removeLastElement +{ + return [self removeElementAtIndex: _count-1]; +} + +- (elt) elementAtIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count); + return _contents_array[GAP_TO_BASIC(index)]; +} + +- appendElement: (elt)newElement +{ + incrementCount(self); + gapMakeHoleAt (self, _count-1); + _contents_array[_count-1] = newElement; + return self; +} + +- prependElement: (elt)newElement +{ + incrementCount(self); + gapMakeHoleAt (self, 0); + _contents_array[0] = newElement; + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count+1); + incrementCount(self); + gapMakeHoleAt (self, index); + _contents_array[index] = newElement; + return self; +} + +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement +{ + elt ret; + + CHECK_INDEX_RANGE_ERROR(index, _count); + ret = _contents_array[GAP_TO_BASIC(index)]; + _contents_array[GAP_TO_BASIC(index)] = newElement; + return self; +} + +- swapAtIndeces: (unsigned)index1 : (unsigned)index2 +{ + elt tmp; + + CHECK_INDEX_RANGE_ERROR(index1, _count); + CHECK_INDEX_RANGE_ERROR(index2, _count); + index1 = GAP_TO_BASIC(index1); + index2 = GAP_TO_BASIC(index2); + tmp = _contents_array[index1]; + _contents_array[index1] = _contents_array[index2]; + _contents_array[index2] = tmp; + return self; +} + +/* Let IndexedCollection take care of this +- shallowCopyReplaceFrom: (unsigned)start to: (unsigned)stop + using: (id )replaceCollection +{ + id newColl = [self shallowCopy]; + unsigned index = start; + BOOL cont = YES; + void doIt (elt e) + { + [newColl replaceElementAtIndex: index with: e]; + cont = (index++ != stop); + } + [replaceCollection withElementsCall: doIt whileTrue: &cont]; + return newColl; +} +*/ + +@end + diff --git a/Source/HashTable.m b/Source/HashTable.m new file mode 100644 index 000000000..6c937d9cd --- /dev/null +++ b/Source/HashTable.m @@ -0,0 +1,361 @@ +/* Implementation of Objective C NeXT-compatible HashTable object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + 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 +#include + +#define DEFAULT_HASH_CAPACITY 32 + + +/* Some useful hash and compare functions not provided by hash.h */ + +static inline unsigned int +hash_object (cache_ptr cache, const void *key) +{ + return (([((id)key) hash]) & cache->mask); +} + +static inline int +compare_objects (const void *k1, const void *k2) +{ + return (int)[(id)k1 isEqual:(id)k2]; +} + +static inline unsigned int +hash_int (cache_ptr cache, const void *key) +{ + return ((unsigned int)key & cache->mask); +} + +static inline int +compare_ints (const void *k1, const void *k2) +{ + return !((int)k1 - (int)k2); +} + +static inline int +compare_long_ints (const void *k1, const void *k2) +{ + return !((long int)k1 - (long int)k2); +} + +@implementation HashTable + ++ initialize +{ + if (self == [HashTable class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- initKeyDesc: (const char *)aKeyDesc + valueDesc: (const char *)aValueDesc + capacity: (unsigned) aCapacity +{ + hash_func_type hf; + compare_func_type cf; + + if (!aKeyDesc) + [self error:"in %s, NULL keyDesc\n", sel_get_name(_cmd)]; + if (!aValueDesc) + [self error:"in %s, NULL valueDesc\n", sel_get_name(_cmd)]; + count = 0; + keyDesc = aKeyDesc; + valueDesc = aValueDesc; + switch (*aKeyDesc) + { + case _C_ATOM: + case _C_CHARPTR : + hf = (hash_func_type)hash_string; + cf = (compare_func_type)compare_strings; + break; + case _C_ID: + case _C_CLASS: + hf = (hash_func_type)hash_object; + cf = (compare_func_type)compare_objects; + break; + case _C_PTR: + hf = (hash_func_type)hash_ptr; + cf = (compare_func_type)compare_ptrs; + break; + case _C_INT: + case _C_SEL: + case _C_UINT: + hf = (hash_func_type)hash_int; + cf = (compare_func_type)compare_ints; + break; + case _C_LNG: + case _C_ULNG: + hf = (hash_func_type)hash_int; + cf = (compare_func_type)compare_long_ints; + break; + case _C_FLT: + /* Fix this. Do something better with floats. */ + hf = (hash_func_type)hash_int; + cf = (compare_func_type)compare_ints; + break; + default: + hf = (hash_func_type)hash_int; + cf = (compare_func_type)compare_ints; + break; + } + _buckets = hash_new(aCapacity, hf, cf); + _nbBuckets = _buckets->size; + return self; +} + +- initKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc +{ + return [self initKeyDesc:aKeyDesc + valueDesc:aValueDesc + capacity:DEFAULT_HASH_CAPACITY]; +} + +- initKeyDesc: (const char *)aKeyDesc +{ + return [self initKeyDesc:aKeyDesc + valueDesc:@encode(id)]; +} + +- init +{ + return [self initKeyDesc:@encode(id)]; +} + +- free +{ + hash_delete(_buckets); + return [super free]; +} + +- freeObjects +{ + node_ptr node; + void *val; + + while ((node = hash_next(_buckets, 0))) + { + val = node->value; + hash_remove(_buckets, node->key); + if (*valueDesc == _C_ID) + [(id)val free]; + } + count = 0; + _nbBuckets = _buckets->size; + return self; +} + +- freeKeys:(void (*) (void *))keyFunc + values:(void (*) (void *))valueFunc +{ + /* What exactly is this supposed to do? */ + [self notImplemented:_cmd]; + return self; +} + +- empty +{ + node_ptr node; + + while ((node = hash_next(_buckets, 0))) + hash_remove(_buckets, node->key); + count = 0; + _nbBuckets = _buckets->size; + return self; +} + +- shallowCopy +{ + HashTable *c; + node_ptr node; + + c = [super shallowCopy]; + c->_buckets = hash_new(_buckets->size, + _buckets->hash_func, + _buckets->compare_func); + /* copy nodes to new copy */ + node = 0; + while ((node = hash_next(_buckets, node))) + [c insertKey:node->key value:node->value]; + + return c; +} + +- deepen +{ + node_ptr node = 0; + + if (*valueDesc == _C_ID) + { + while ((node = hash_next(_buckets, node))) + { + node->value = [(id)(node->value) deepCopy]; + } + } + /* If the hashtable contains strings should we copy them too?? + But we definitely shouldn't copy "%" keys. */ + return self; +} + +- (unsigned) count +{ + return count; +} + +- (BOOL) isKey:(const void *)aKey +{ + return (hash_value_for_key(_buckets, aKey)) ? YES : NO; +} + +- (void *) valueForKey:(const void *)aKey +{ + return hash_value_for_key(_buckets, aKey); +} + +- (void *) insertKey:(const void *)aKey value:(void *)aValue +{ + void *prevValue; + + prevValue = hash_value_for_key(_buckets, aKey); + if (prevValue) + hash_remove(_buckets, aKey); + hash_add(&_buckets, aKey, aValue); + count = _buckets->used; + _nbBuckets = _buckets->size; + return prevValue; +} + +- (void *) removeKey:(const void *)aKey +{ + if (hash_value_for_key(_buckets, aKey)) + { + hash_remove(_buckets, aKey); + count = _buckets->used; + _nbBuckets = _buckets->size; + } + return nil; +} + +- (NXHashState) initState +{ + return (NXHashState) 0; +} + +- (BOOL) nextState:(NXHashState *)aState + key:(const void **)aKey + value:(void **)aValue +{ + *aState = hash_next(_buckets, *aState); + if (*aState) + { + *aKey = (*aState)->key; + *aValue = (*aState)->value; + return YES; + } + else + return NO; +} + +- write: (TypedStream*)aStream +{ + NXHashState state = [self initState]; + const void *k; + void *v; + + if (!strcmp(keyDesc, "%")) + [self error:"Archiving atom strings, @encode()=\"%\", not yet handled"]; + [super write: aStream]; + objc_write_types(aStream, "II**", + [self count], _nbBuckets, keyDesc, valueDesc); + while ([self nextState:&state key:&k value:&v]) + { + objc_write_type(aStream, keyDesc, &k); + objc_write_type(aStream, valueDesc, &v); + } + return self; +} + +- read: (TypedStream*)aStream +{ + unsigned cnt, capacity; + int i; + const void *k; + void *v; + + [super read:aStream]; + objc_read_types(aStream, "II**", + &cnt, &capacity, &keyDesc, &valueDesc); + if (!strcmp(keyDesc, "%")) + [self error:"Archiving atom strings, @encode()=\"%\", not yet handled"]; + [self initKeyDesc:keyDesc valueDesc:valueDesc capacity:capacity]; + for (i = 0; i < cnt; i++) + { + objc_read_type(aStream, keyDesc, &k); + objc_read_type(aStream, valueDesc, &v); + [self insertKey:k value:v]; + } + return self; +} + + ++ newKeyDesc: (const char *)aKeyDesc +{ + return [[[self class] alloc] initKeyDesc:aKeyDesc]; +} + ++ newKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc +{ + return [[self alloc] + initKeyDesc:aKeyDesc + valueDesc:aValueDesc]; +} + ++ newKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc + capacity:(unsigned)aCapacity +{ + return [[self alloc] + initKeyDesc:aKeyDesc + valueDesc:aValueDesc + capacity:aCapacity]; +} + +- makeObjectsPerform:(SEL)aSel +{ + node_ptr node = 0; + + while ((node = hash_next(_buckets, node))) + [(id)(node->value) perform:aSel]; + return self; +} + +- makeObjectsPerform:(SEL)aSel with:anObject +{ + node_ptr node = 0; + + while ((node = hash_next(_buckets, node))) + [(id)(node->value) perform:aSel with:anObject]; + return self; +} + +@end diff --git a/Source/Heap.m b/Source/Heap.m new file mode 100644 index 000000000..fbe7da027 --- /dev/null +++ b/Source/Heap.m @@ -0,0 +1,98 @@ +/* Implementation for Objective-C Heap object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#define HEAP_PARENT(i) (i/2) +#define HEAP_LEFT(i) (2 * i) +#define HEAP_RIGHT(i) ((2 * i) + 1) + +@implementation Heap + +/* We could take out the recursive call to make it a little more efficient */ +- heapifyFromIndex: (unsigned)index +{ + unsigned right, left, largest; + elt tmp; + + right = HEAP_RIGHT(index); + left = HEAP_LEFT(index); + if (left <= _count + && COMPARE_ELEMENTS(_contents_array[left],_contents_array[index]) > 0) + largest = left; + else + largest = index; + if (right <= _count + && COMPARE_ELEMENTS(_contents_array[right],_contents_array[largest]) > 0) + largest = right; + if (largest != index) + { + tmp = _contents_array[index]; + _contents_array[index] = _contents_array[largest]; + _contents_array[largest] = tmp; + [self heapifyFromIndex:largest]; + } + return self; +} + +- heapify +{ + int i; + + // could use objc_msg_lookup here; + for (i = _count / 2; i >= 1; i--) + [self heapifyFromIndex:i]; + return self; +} + +- (elt) removeFirstElement +{ + elt ret; + + if (_count == 0) + NO_ELEMENT_FOUND_ERROR(); + ret = _contents_array[0]; + _contents_array[0] = _contents_array[_count-1]; + decrementCount(self); + [self heapifyFromIndex:0]; + return ret; +} + +- addElement: (elt)newElement +{ + int i; + + incrementCount(self); + for (i = _count-1; + i > 0 + && COMPARE_ELEMENTS(_contents_array[HEAP_PARENT(i)], newElement) < 0; + i = HEAP_PARENT(i)) + { + _contents_array[i] = _contents_array[HEAP_PARENT(i)]; + } + _contents_array[i] = newElement; + return self; +} + +@end diff --git a/Source/IndexedCollection.m b/Source/IndexedCollection.m new file mode 100644 index 000000000..0bd2888d8 --- /dev/null +++ b/Source/IndexedCollection.m @@ -0,0 +1,1120 @@ +/* Implementation for Objective-C IndexedCollection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +@implementation IndexedCollection + ++ initialize +{ + if (self == [IndexedCollection class]) + [self setVersion:0]; /* beta release */ + return self; +} + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding +{ + [super initWithType:contentEncoding + keyType:@encode(unsigned int)]; + return self; +} + +/* Override the designated initializer for our superclass KeyedCollection + to make sure we have unsigned int keys. */ +- initWithType: (const char *)contentEncoding + keyType: (const char *)keyEncoding +{ + if (strcmp(keyEncoding, @encode(unsigned int))) + [self error:"IndexedCollection key must be an unsigned integer."]; + return [self initWithType:contentEncoding]; +} + +// ADDING; + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + return [self subclassResponsibility:_cmd]; +} + +/* Semantics: You can "put" an element only at index "count" or less */ +- putElement: (elt)newElement atIndex: (unsigned)index +{ + unsigned c = [self count]; + + if (index < c) + [self replaceElementAtIndex:index with:newElement]; + else if (index == c) + [self appendElement:newElement]; + else + [self error:"in %s, can't put an element at index beyond [self count]"]; + return self; +} + +- putElement: (elt)newElement atKey: (elt)index +{ + return [self putElement: newElement atIndex: index.unsigned_int_u]; +} + +- insertObject: newObject atIndex: (unsigned)index +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self insertElement:newObject atIndex:index]; +} + +- insertElement: (elt)newElement before: (elt)oldElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + [self insertElement:newElement atIndex:index]; + return self; +} + +- insertObject: newObject before: oldObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self insertElement:newObject before:oldObject]; +} + +- insertElement: (elt)newElement after: (elt)oldElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + [self insertElement:newElement atIndex:index+1]; + return self; +} + +- insertObject: newObject after: oldObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self insertElement:newObject after:oldObject]; +} + +/* Possibly inefficient. Should be overridden. */ +- appendElement: (elt)newElement +{ + return [self insertElement:newElement atIndex:[self count]]; +} + +- appendObject: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self appendElement:newObject]; +} + +/* Possibly inefficient. Should be overridden. */ +- prependElement: (elt)newElement +{ + return [self insertElement:newElement atIndex:0]; +} + +- prependObject: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self prependElement:newObject]; +} + +- appendContentsOf: (id ) aCollection +{ + void doIt(elt e) + { + [self appendElement:e]; + } + if (aCollection == self) + [self safeWithElementsCall:doIt]; + else + [aCollection withElementsCall:doIt]; + return self; +} + +- prependContentsOf: (id ) aCollection +{ + void doIt(elt e) + { + /* could use objc_msg_lookup here */ + [self prependElement:e]; + } + if (aCollection == self) + [self safeWithElementsInReverseCall:doIt]; + else + { + /* Can I assume that all Collections will inherit from Object? */ + if ([aCollection + respondsTo:@selector(withElementsInReverseCall:)]) + [(id)aCollection withElementsInReverseCall:doIt]; + else + [aCollection withElementsCall:doIt]; + } + return self; +} + +- addContentsOf: (id )aCollection +{ + [self appendContentsOf:aCollection]; + return self; +} + +- insertContentsOf: (id )aCollection atIndex: (unsigned)index +{ + void doIt(elt e) + { + [self insertElement: e atIndex: index]; + } + if (aCollection == self) + [self safeWithElementsInReverseCall:doIt]; + else + { + if ([aCollection respondsTo:@selector(withElemetnsInReverseCall:)]) + [(id)aCollection withElementsInReverseCall:doIt]; + else + [aCollection withElementsCall:doIt]; + } + return self; +} + +/* We can now implement this protocol method */ +- addElement: (elt)newElement +{ + return [self appendElement:newElement]; +} + + +// REPLACING; + +/* Subclasses may require different ordering semantics */ +- (elt) replaceElement: (elt)oldElement with: (elt)newElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + return [self replaceElementAtIndex:index with:newElement]; +} + +/* Inefficient. Should be overridden */ +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement +{ + elt ret; + + ret = [self removeElementAtIndex:index]; + [self insertElement:newElement atIndex:index]; + return ret; +} + +- replaceObjectAtIndex: (unsigned)index with: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self replaceElementAtIndex:index with:newObject].id_u; +} + +- replaceRange: (IndexRange)aRange + with: (id )aCollection +{ + CHECK_INDEX_RANGE_ERROR(aRange.start, [self count]); + CHECK_INDEX_RANGE_ERROR(aRange.end-1, [self count]); + [self removeRange:aRange]; + [self insertContentsOf:aCollection atIndex:aRange.start]; + return self; +} + +- replaceRange: (IndexRange)aRange + using: (id )aCollection +{ + int i; + void *state = [aCollection newEnumState]; + elt e; + + CHECK_INDEX_RANGE_ERROR(aRange.start, [self count]); + CHECK_INDEX_RANGE_ERROR(aRange.end-1, [self count]); + for (i = aRange.start; + i < aRange.end + && [aCollection getNextElement:&e withEnumState:&state]; + i++) + { + [self replaceElementAtIndex:i with:e]; + } + [aCollection freeEnumState:&state]; + return self; +} + + +// SWAPPING; + +/* Perhaps inefficient. May be overridden. */ +- swapAtIndeces: (unsigned)index1 : (unsigned)index2 +{ + elt tmp = [self elementAtIndex:index1]; + [self replaceElementAtIndex:index1 with:[self elementAtIndex:index2]]; + [self replaceElementAtIndex:index2 with:tmp]; + return self; +} + + +// REMOVING; + +- (elt) removeElementAtIndex: (unsigned)index +{ + return [self subclassResponsibility:_cmd]; +} + +- removeObjectAtIndex: (unsigned)index +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeElementAtIndex:index].id_u; +} + +- (elt) removeFirstElement +{ + return [self removeElementAtIndex:0]; +} + +- removeFirstObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeFirstElement].id_u; +} + +- (elt) removeLastElement +{ + return [self removeElementAtIndex:[self count]-1]; +} + +- removeLastObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeLastElement].id_u; +} + +- removeRange: (IndexRange)aRange +{ + int i; + + CHECK_INDEX_RANGE_ERROR(aRange.start, [self count]); + CHECK_INDEX_RANGE_ERROR(aRange.end-1, [self count]); + for (i = aRange.start; i < aRange.end; i++) + [self removeElementAtIndex:aRange.start]; + return self; +} + +/* We can now implement this protocol method */ +- (elt) removeElement: (elt)oldElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + return [self removeElementAtIndex:index]; +} + + +// GETTING MEMBERS BY INDEX; + +- (elt) elementAtIndex: (unsigned)index +{ + return [self subclassResponsibility:_cmd]; +} + +- objectAtIndex: (unsigned)index +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self elementAtIndex:index].id_u; +} + +- (elt) firstElement +{ + return [self elementAtIndex:0]; +} + +- firstObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self firstElement].id_u; +} + +- (elt) lastElement +{ + return [self elementAtIndex:[self count]-1]; +} + +- lastObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self lastElement].id_u; +} + + +// GETTING MEMBERS BY NEIGHBOR; + +// This method should be overridden by linkedlists and trees; +- (elt) successorOfElement: (elt)oldElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + return [self elementAtIndex:index+1]; +} + +// This method should be overridden by linkedlists and trees; +- (elt) predecessorOfElement: (elt)oldElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(oldElement); + return 0; + } + unsigned index = [self indexOfElement:oldElement ifAbsentCall:err]; + + return [self elementAtIndex:index-1]; +} + +- successorOfObject: anObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self successorOfElement:anObject].id_u; +} + +- predecessorOfObject: anObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self predecessorOfElement:anObject].id_u; +} + + +// GETTING INDICES BY ELEMENT; + +/* Possibly inefficient. */ +- (unsigned) indexOfElement: (elt)anElement +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(anElement); + return 0; + } + return [self indexOfElement:anElement ifAbsentCall:err]; +} + +- (unsigned) indexOfElement: (elt)anElement + ifAbsentCall: (unsigned(*)(arglist_t))excFunc +{ + unsigned index = 0; + BOOL flag = YES; + int (*cf)(elt,elt) = [self comparisonFunction]; + void doIt(elt e) + { + if (!((*cf)(anElement, e))) + flag = NO; + else + index++; + } + + [self withElementsCall:doIt whileTrue:&flag]; + if (flag) + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + return index; +} + +- (unsigned) indexOfObject: anObject + ifAbsentCall: (unsigned(*)(arglist_t))excFunc +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self indexOfElement:anObject ifAbsentCall:excFunc]; +} + +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange +{ + unsigned err(arglist_t argFrame) + { + ELEMENT_NOT_FOUND_ERROR(anElement); + return 0; + } + return [self indexOfElement:anElement inRange:aRange ifAbsentCall:err]; +} + +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self indexOfElement:anObject inRange:aRange]; +} + +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc +{ + int i; + int (*cf)(elt,elt) = [self comparisonFunction]; + + for (i = aRange.start; i < aRange.end; i++) + if (!((*cf)(anElement, [self elementAtIndex:i]))) + return i - aRange.start; + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); +} + +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self indexOfElement:anObject inRange:aRange ifAbsentCall:excFunc]; +} + +- (unsigned) indexOfFirstDifference: (id )aColl +{ + unsigned i = 0; + BOOL flag = YES; + void *enumState = [self newEnumState]; + int (*cf)(elt,elt); + elt e2; + void doIt(elt e1) + { + if ((![self getNextElement:&e2 withEnumState:&enumState]) + || ((*cf)(e1, e2))) + flag = NO; + else + i++; + } + + if ((cf = [self comparisonFunction]) != [aColl comparisonFunction]) + return 0; + [aColl withElementsCall:doIt whileTrue:&flag]; + [self freeEnumState:&enumState]; + return i; +} + +/* Could be more efficient */ +- (unsigned) indexOfFirstIn: (id )aColl +{ + unsigned index = 0; + BOOL flag = YES; + void doIt(elt e) + { + if ([aColl includesElement:e]) + flag = NO; + else + index++; + } + if ([self comparisonFunction] != [aColl comparisonFunction]) + return [self count]; + [self withElementsCall:doIt whileTrue:&flag]; + return index; +} + +/* Could be more efficient */ +- (unsigned) indexOfFirstNotIn: (id )aColl +{ + unsigned index = 0; + BOOL flag = YES; + void doIt(elt e) + { + if (![aColl includesElement:e]) + flag = NO; + else + index++; + } + if ([self comparisonFunction] != [aColl comparisonFunction]) + return [self count]; + [self withElementsCall:doIt whileTrue:&flag]; + return index; +} + +- (unsigned) indexOfObject: anObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self indexOfElement:anObject]; +} + +// TESTING; + +- (const char *) keyDescription +{ + return @encode(unsigned int); +} + +- (BOOL) includesIndex: (unsigned)index +{ + if (index < [self count]) + return YES; + else + return NO; +} + +- (BOOL) contentsEqualInOrder: (id )anIndexedColl +{ + elt e1, e2; + void *s1, *s2; + int (*cf)(elt,elt) = [self comparisonFunction]; + + if ([self count] != [anIndexedColl count]) + return NO; + s1 = [self newEnumState]; + s2 = [anIndexedColl newEnumState]; + while ([self getNextElement:&e1 withEnumState:&s1] + && [anIndexedColl getNextElement:&e2 withEnumState:&s2]) + { + if ((*cf)(e1, e2)) + return NO; + } + [self freeEnumState:&s1]; + [anIndexedColl freeEnumState:&s2]; + return YES; +} + +/* is this what we want? */ +- (BOOL) isEqual: anObject +{ + if (self == anObject) + return YES; + if ([anObject class] == [self class] + && [self count] != [anObject count] + && [self contentsEqualInOrder: anObject] ) + return YES; + else + return NO; +} + +- (int) compareContentsOfInOrder: (id )aCollection +{ + int (*cf)(elt,elt) = [self comparisonFunction]; + if ([aCollection comparisonFunction] == cf) + { + void *es1 = [self newEnumState]; + void *es2 = [aCollection newEnumState]; + elt e1, e2; + int comparison; + while ([self getNextElement:&e1 withEnumState:&es1] + && [aCollection getNextElement:&e1 withEnumState:&es2]) + { + if ((comparison = (*cf)(e1,e2))) + { + [self freeEnumState:&es1]; + [aCollection freeEnumState:&es2]; + return comparison; + } + } + if ((comparison = ([self count] - [aCollection count]))) + return comparison; + return 0; + } + [self error:"Can't compare contents of collections with different " + "comparison functions"]; + return -1; +} + + +// COPYING; + +- shallowCopyRange: (IndexRange)aRange +{ + id newColl = [self emptyCopyAs:[self species]]; + unsigned i, myCount = [self count]; + + for (i = aRange.start; i < aRange.end && i < myCount; i++) + [newColl addElement:[self elementAtIndex:i]]; + return newColl; +} + +- withElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc +{ + unsigned i, myCount = [self count]; + + for (i = aRange.start; i < aRange.end && i < myCount; i++) + (*aFunc)([self elementAtIndex:i]); + return self; +} + +- withObjectsInRange: (IndexRange)aRange call:(void(*)(id))aFunc +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsInRange:aRange call:doIt]; +} + +- safeWithElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc +{ + unsigned i, myCount = [self count]; + id tmpColl = [[Array alloc] initWithType:[self contentType] + capacity:aRange.end - aRange.start]; + + for (i = aRange.start; i < aRange.end && i < myCount; i++) + [tmpColl addElement:[self elementAtIndex:i]]; + [tmpColl withElementsCall:aFunc]; + [tmpColl free]; + return self; +} + +- shallowCopyReplaceRange: (IndexRange)aRange + with: (id )replaceCollection +{ + id newColl = [self emptyCopyAs:[self species]]; + unsigned i, myCount = [self count]; + + for (i = 0; i < aRange.start && i < myCount; i++) + [newColl appendElement:[self elementAtIndex:i]]; + [newColl appendContentsOf:replaceCollection]; + for (i = aRange.end; i < myCount; i++) + [newColl appendElement:[self elementAtIndex:i]]; + return newColl; +} + +- shallowCopyReplaceRange: (IndexRange)aRange + using: (id )replaceCollection +{ + id newColl = [self shallowCopy]; + unsigned index = aRange.start; + BOOL cont = YES; + void doIt (elt e) + { + [newColl replaceElementAtIndex: index with: e]; + cont = (++index != aRange.end); + } + [replaceCollection withElementsCall: doIt whileTrue: &cont]; + return newColl; +} + +- shallowCopyInReverseAs: aCollectionClass +{ + id newColl = [self emptyCopyAs:aCollectionClass]; + void doIt(elt e) + { + [newColl appendElement:e]; + } + [self withElementsInReverseCall:doIt]; + return self; +} + + +// ENUMERATING; + +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState +{ + /* *(unsigned*)enumState is the index of the element that will be returned */ + if ((*(unsigned*)enumState) > [self count]-1) + return NO; + *anElementPtr = [self elementAtIndex:(*(unsigned*)enumState)]; + *aKeyPtr = (*(unsigned*)enumState); + (*(unsigned*)enumState)++; + return YES; +} + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + /* *(unsigned*)enumState is the index of the element that will be returned */ + if ((*(unsigned*)enumState) > [self count]-1) + return NO; + *anElementPtr = [self elementAtIndex:(*(unsigned*)enumState)]; + (*(unsigned*)enumState)++; + return YES; +} + +- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + /* *(unsigned*)enumState-1 is the index of the element + that will be returned */ + if (!(*enumState)) + *(unsigned*)enumState = [self count]-1; + else + (*(unsigned*)enumState)--; + *anElementPtr = [self elementAtIndex:(*(unsigned*)enumState)]; + return YES; +} + +- (BOOL) getPrevObject:(id *)anObjectPtr withEnumState: (void**)enumState +{ + /* *(unsigned*)enumState-1 is the index of the element + that will be returned */ + CHECK_CONTAINS_OBJECTS_ERROR(); + if (!(*enumState)) + *(unsigned*)enumState = [self count]-1; + else + (*(unsigned*)enumState)--; + *anObjectPtr = [self elementAtIndex:(*(unsigned*)enumState)].id_u; + return YES; +} + +- withElementsInReverseCall: (void(*)(elt))aFunc; +{ + BOOL flag = NO; + [self withElementsInReverseCall:aFunc whileTrue:&flag]; + return self; +} + +- safeWithElementsInReverseCall: (void(*)(elt))aFunc; +{ + BOOL flag = NO; + [self safeWithElementsInReverseCall:aFunc whileTrue:&flag]; + return self; +} + +- withObjectsInReverseCall: (void(*)(id))aFunc +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsInReverseCall:doIt]; +} + +- safeWithObjectsInReverseCall: (void(*)(id))aFunc +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsInReverseCall:doIt]; +} + +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + int i; + + for (i = [self count]-1; *flag && i >= 0; i--) + (*aFunc)([self elementAtIndex:i]); + return self; +} + +- safeWithElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + id tmp = [[Array alloc] initWithContentsOf:self]; + [tmp withElementsInReverseCall:aFunc whileTrue:flag]; + [tmp free]; + return self; +} + +- withObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsInReverseCall:doIt whileTrue:flag]; +} + +- safeWithObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag +{ + void doIt(elt e) + { + (*aFunc)(e.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsInReverseCall:doIt whileTrue:flag]; +} + +- makeObjectsPerformInReverse: (SEL)aSel +{ + void doIt(elt e) + { + [e.id_u perform:aSel]; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsInReverseCall:doIt]; +} + +- safeMakeObjectsPerformInReverse: (SEL)aSel +{ + void doIt(elt e) + { + [e.id_u perform:aSel]; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsInReverseCall:doIt]; +} + +- makeObjectsPerformInReverse: (SEL)aSel with: argObject +{ + void doIt(elt e) + { + [e.id_u perform:aSel with:argObject]; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self withElementsInReverseCall:doIt]; +} + +- safeMakeObjectsPerformInReverse: (SEL)aSel with: argObject +{ + void doIt(elt e) + { + [e.id_u perform:aSel with:argObject]; + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self safeWithElementsInReverseCall:doIt]; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + unsigned i; + unsigned count = [self count]; + + for (i = 0; *flag && i < count; i++) + (*aFunc)([self elementAtIndex:i]); + return self; +} + +- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc + whileTrue: (BOOL *)flag +{ + unsigned index = 0; + void doIt(elt e) + { + (*aFunc)(index, e); + index++; + } + [self withElementsCall:doIt]; + return self; +} + + +// SORTING; + +/* This could be hacked a bit to make it more efficient */ +- quickSortContentsFromIndex: (unsigned)p + toIndex: (unsigned)r + byCalling: (int(*)(elt,elt))aFunc +{ + unsigned i ,j; + elt x; + + if (p < r) + { + /* Partition */ + x = [self elementAtIndex:p]; + i = p - 1; + j = r + 1; + for (;;) + { + do + j = j - 1; + while ((*aFunc)([self elementAtIndex:j],x) > 0); + do + i = i + 1; + while ((*aFunc)([self elementAtIndex:i],x) < 0); + if (i < j) + [self swapAtIndeces:i :j]; + else + break; + } + /* Sort partitions */ + [self quickSortContentsFromIndex:p toIndex:j byCalling:aFunc]; + [self quickSortContentsFromIndex:j+1 toIndex:r byCalling:aFunc]; + } + return self; +} + +- sortElementsByCalling: (int(*)(elt,elt))aFunc +{ + if ([self count] == 0) + return self; + [self quickSortContentsFromIndex:0 + toIndex:[self count]-1 + byCalling:aFunc]; + return self; +} + +- sortObjectsByCalling: (int(*)(id,id))aFunc +{ + int comp(elt e1, elt e2) + { + return (*aFunc)(e1.id_u, e2.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self sortElementsByCalling:comp]; +} + +- sortContents +{ + [self sortElementsByCalling:COMPARISON_FUNCTION]; + return self; +} + +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc +{ + unsigned insertionIndex = 0; + BOOL insertionNotFound = YES; + void test(elt e) + { + if ((*aFunc)(newElement, e) < 0) + insertionNotFound = NO; + else + insertionIndex++; + } + [self withElementsCall:test whileTrue:&insertionNotFound]; + [self insertElement:newElement atIndex:insertionIndex]; + return self; +} + +- sortAddElement: (elt)newElement +{ + return [self sortAddElement:newElement byCalling:COMPARISON_FUNCTION]; +} + +- sortAddObject: newObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return[self sortAddElement:newObject]; +} + +- sortAddObject: newObject byCalling: (int(*)(id,id))aFunc +{ + int comp(elt e1, elt e2) + { + return (*aFunc)(e1.id_u, e2.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self sortAddElement:newObject byCalling:comp]; +} + + +// RELATION WITH KeyedCollection; + +- insertElement: (elt)newContentElement atKey: (elt)aKey +{ + return [self insertElement:newContentElement atIndex:aKey.unsigned_int_u]; +} + +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement +{ + return [self replaceElementAtIndex:aKey.unsigned_int_u + with:newContentElement]; +} + +- (elt) removeElementAtKey: (elt)aKey +{ + return [self removeElementAtIndex:aKey.unsigned_int_u]; +} + +- (elt) elementAtKey: (elt)aKey +{ + return [self elementAtIndex:aKey.unsigned_int_u]; +} + +- (BOOL) includesKey: (elt)aKey +{ + return [self includesIndex:aKey.unsigned_int_u]; +} + +- printForDebugger +{ + void doIt(elt e) + { + [self printElement:e]; + printf(" "); + } + [self withElementsCall:doIt]; + printf(" :%s\n", [self name]); + return self; +} + +- (void) _encodeContentsWithCoder: (Coder*)coder +{ + unsigned int count = [self count]; + const char *encoding = [self contentType]; + void archiveElement(elt e) + { + [coder encodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &e) + withName:"IndexedCollection Element"]; + } + + [coder encodeValueOfSimpleType:@encode(unsigned int) + at:&count + withName:"IndexedCollection Contents Count"]; + [self withElementsCall:archiveElement]; +} + +- (void) _decodeContentsWithCoder: (Coder*)coder +{ + unsigned int count, i; + elt newElement; + const char *encoding = [self contentType]; + + [coder decodeValueOfSimpleType:@encode(unsigned int) + at:&count + withName:NULL]; + for (i = 0; i < count; i++) + { + [coder decodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &newElement) + withName:NULL]; + [self appendElement:newElement]; + } +} + +- _writeContents: (TypedStream*)aStream +{ + unsigned int count = [self count]; + const char *encoding = [self contentType]; + void archiveElement(elt e) + { + objc_write_types(aStream, encoding, + elt_get_ptr_to_member(encoding, &e)); + } + + objc_write_type(aStream, @encode(unsigned int), &count); + [self withElementsCall:archiveElement]; + return self; +} + +- _readContents: (TypedStream*)aStream +{ + unsigned int count, i; + elt newElement; + const char *encoding = [self contentType]; + + objc_read_type(aStream, @encode(unsigned int), &count); + for (i = 0; i < count; i++) + { + objc_read_types(aStream, encoding, + elt_get_ptr_to_member(encoding, &newElement)); + [self appendElement:newElement]; + } + return self; +} + +@end + diff --git a/Source/KeyedCollection.m b/Source/KeyedCollection.m new file mode 100644 index 000000000..ec4c6cbff --- /dev/null +++ b/Source/KeyedCollection.m @@ -0,0 +1,550 @@ +/* Implementation for Objective-C KeyedCollection collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +@implementation KeyedCollection + ++ initialize +{ + if (self == [KeyedCollection class]) + [self setVersion:0]; /* beta release */ + return self; +} + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING; + +/* This is the designated initializer of this class */ +- initWithType: (const char *)contentEncoding + keyType: (const char *)keyEncoding +{ + [super initWithType:contentEncoding]; + if (!elt_get_comparison_function(contentEncoding)) + [self error:"There is no elt comparison function for type encoding %s", + keyEncoding]; + return self; +} + +- initKeyType: (const char *)keyEncoding +{ + // default contents are objects; + return [self initWithType:@encode(id) keyType:keyEncoding]; +} + +/* Override designated initializer of superclass */ +- initWithType: (const char *)contentEncoding +{ + // default keys are objects; + return [self initWithType:contentEncoding + keyType:@encode(id)]; +} + +- free +{ + // ?? ; + return [super free]; +} + + +// ADDING OR REPLACING; + +- putElement: (elt)newContentElement atKey: (elt)aKey +{ + return [self subclassResponsibility:_cmd]; +} + +- addContentsOf: (id )aKeyedCollection +{ + id (*putElementAtKeyImp)(id,SEL,elt,elt) = (id(*)(id,SEL,elt,elt)) + objc_msg_lookup(self, @selector(putElement:atKey:)); + void doIt(elt k, elt c) + { + (*putElementAtKeyImp)(self, @selector(putElement:atKey:), + c, k); + } + [aKeyedCollection withKeyElementsAndContentElementsCall:doIt]; + return self; +} + +/* The right thing? Or should this be subclass responsibility? */ +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(aKey); + } + return [self replaceElementAtKey:aKey with:newContentElement + ifAbsentCall:err]; +} + +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; +{ + elt err(arglist_t argFrame) + { + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + } + elt ret; + + ret = [self removeElementAtKey:aKey ifAbsentCall:err]; + [self putElement:newContentElement atKey:aKey]; + return ret; +} + +- swapAtKeys: (elt)key1 : (elt)key2 +{ + /* Use two tmp's so that when we add reference counting, the count will + stay correct. */ + elt tmp1 = [self removeElementAtKey:key1]; + elt tmp2 = [self removeElementAtKey:key2]; + [self putElement:tmp2 atKey:key1]; + [self putElement:tmp1 atKey:key2]; + return self; +} + +// REMOVING; + +- (elt) removeElementAtKey: (elt)aKey +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(aKey); + } + return [self removeElementAtKey:aKey ifAbsentCall:err]; +} + +- (elt) removeElementAtKey: (elt)aKey + ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + return [self subclassResponsibility:_cmd]; +} + +- removeObjectAtKey: (elt)aKey +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self removeElementAtKey:aKey].id_u; +} + + +// GETTING ELEMENTS AND KEYS; + +- (elt) elementAtKey: (elt)aKey +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(aKey); + } + return [self elementAtKey:aKey ifAbsentCall:err]; +} + +- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + return [self subclassResponsibility:_cmd]; +} + +- (elt) keyElementOfElement: (elt)aContent +{ + elt err(arglist_t argFrame) + { + return ELEMENT_NOT_FOUND_ERROR(aContent); + } + return [self keyElementOfElement:aContent ifAbsentCall:err]; +} + +- (elt) keyElementOfElement: (elt)aContent + ifAbsentCall: (elt(*)(arglist_t))excFunc +{ + elt theKey; + BOOL notDone = YES; + int (*cf)(elt,elt) = [self comparisonFunction]; + void doIt(elt key, elt content) + { + if (!((*cf)(aContent, content))) + { + theKey = key; + notDone = NO; + } + } + [self withKeyElementsAndContentElementsCall:doIt whileTrue:¬Done]; + if (notDone) + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + return theKey; +} + +- objectAtKey: (elt)aKey +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self elementAtKey:aKey].id_u; +} + +- keyObjectOfObject: aContent +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self keyElementOfElement:aContent].id_u; +} + + +// TESTING; + +- (const char *) keyType +{ + [self subclassResponsibility:_cmd]; + return ""; +} + +- (BOOL) includesKey: (elt)aKey +{ + [self subclassResponsibility:_cmd]; + return NO; +} + +// COPYING; + +- shallowCopyAs: (id )aCollectionClass +{ + id (*putElementAtKeyImp)(id,SEL,elt,elt); + id newColl; + + void addKeysAndContents(const elt key, elt content) + { + putElementAtKeyImp(newColl, @selector(putElement:atKey:), + content, key); + } + + if ([aCollectionClass conformsTo:@protocol(KeyedCollecting)]) + { + newColl = [self emptyCopyAs:aCollectionClass]; + putElementAtKeyImp = (id(*)(id,SEL,elt,elt)) + objc_msg_lookup(newColl, @selector(putElement:atKey:)); + [self withKeyElementsAndContentElementsCall:addKeysAndContents]; + return newColl; + } + else + return [super shallowCopyAs:aCollectionClass]; +} + + +// ENUMERATING; + +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState; +{ + [self subclassResponsibility:_cmd]; + return NO; +} + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + elt key; + return [self getNextKey:&key content:anElementPtr + withEnumState:enumState]; +} + +- withKeyElementsCall: (void(*)(const elt))aFunc +{ + void doIt(elt key, elt content) + { + (*aFunc)(key); + } + [self withKeyElementsAndContentElementsCall:doIt]; + return self; +} + +- safeWithKeyElementsCall: (void(*)(const elt))aFunc +{ + id tmpColl = [[Array alloc] initWithType:[self keyType] + capacity:[self count]]; + void addKey(elt k, elt c) + { + [tmpColl addElement:k]; + } + [self withKeyElementsAndContentElementsCall:addKey]; + [tmpColl withElementsCall:aFunc]; + [tmpColl free]; + return self; +} + +- withKeyObjectsCall: (void(*)(id))aFunc +{ + void doIt(elt key, elt content) + { + (*aFunc)(key.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withKeyElementsAndContentElementsCall:doIt]; + return self; +} + +- safeWithKeyObjectsCall: (void(*)(id))aFunc +{ + void doIt(elt key) + { + (*aFunc)(key.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithKeyElementsCall:doIt]; + return self; +} + +- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc +{ + BOOL flag = YES; + + [self withKeyElementsAndContentElementsCall:aFunc whileTrue:&flag]; + return self; +} + +- safeWithKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc +{ + BOOL flag = YES; + + [self safeWithKeyElementsAndContentElementsCall:aFunc whileTrue:&flag]; + return self; +} + +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc +{ + BOOL flag = YES; + void doIt(elt k, elt c) + { + (*aFunc)(k.id_u, c.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withKeyElementsAndContentElementsCall:doIt whileTrue:&flag]; + return self; +} + +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc +{ + BOOL flag = YES; + void doIt(elt k, elt c) + { + (*aFunc)(k.id_u, c.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithKeyElementsAndContentElementsCall:doIt whileTrue:&flag]; + return self; +} + +- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc + whileTrue: (BOOL *)flag +{ + void *s = [self newEnumState]; + elt key, content; + + while (*flag && [self getNextKey:&key content:&content withEnumState:&s]) + (*aFunc)(key, content); + [self freeEnumState:&s]; + return self; +} + +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag +{ + void doIt(elt k, elt c) + { + (*aFunc)(k.id_u, c.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self withKeyElementsAndContentElementsCall:doIt whileTrue:flag]; + return self; +} + +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag +{ + void doIt(elt k, elt c) + { + (*aFunc)(k.id_u, c.id_u); + } + CHECK_CONTAINS_OBJECTS_ERROR(); + [self safeWithKeyElementsAndContentElementsCall:doIt whileTrue:flag]; + return self; +} + +- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc + whileTrue: (BOOL *)flag +{ + int i, count = [self count]; + id keyTmpColl = [[Array alloc] initWithType:[self keyType] + capacity:count]; + id contentTmpColl = [[Array alloc] initWithType:[self contentType] + capacity:count]; + void appendKeyAndContent(elt k, elt c) + { + [keyTmpColl appendElement:k]; + [contentTmpColl appendElement:c]; + } + [self withKeyElementsAndContentElementsCall:appendKeyAndContent]; + for (i = 0; *flag && i < count; i++) + (*aFunc)([keyTmpColl elementAtIndex:i], [contentTmpColl elementAtIndex:i]); + [keyTmpColl free]; + [contentTmpColl free]; + return self; +} + + +// ADDING OR REPLACING; + +- putObject: newContentObject atKey: (elt)aKey +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self putElement:newContentObject atKey:aKey]; +} + +- replaceObjectAtKey: (elt)aKey with: newContentObject +{ + CHECK_CONTAINS_OBJECTS_ERROR(); + return [self replaceElementAtKey:aKey with:newContentObject].id_u; +} + + +// GETTING COLLECTIONS OF CONTENTS SEPARATELY; + +- shallowCopyKeysAs: aCollectionClass; +{ + id newColl = [self emptyCopyAs:aCollectionClass]; + id(*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) + objc_msg_lookup(newColl, @selector(addElement:)); + void doIt(elt e) + { + addElementImp(newColl, @selector(addElement:), e); + } + + [self withKeyElementsCall:doIt]; + return self; +} + +- shallowCopyContentsAs: aCollectionClass +{ + return [super shallowCopyAs:aCollectionClass]; +} + + +// ENUMERATIONS; + +- printForDebugger +{ + const char *kd = [self keyType]; + const char *cd = [self contentType]; + void doIt(const elt key, elt content) + { + printf("("); + elt_fprintf_elt(stdout, kd, key); + printf(","); + elt_fprintf_elt(stdout, cd, content); + printf(") "); + } + [self withKeyElementsAndContentElementsCall:doIt]; + printf(" :%s\n", [self name]); + return self; +} + +- (void) _encodeContentsWithCoder: (Coder*)aCoder +{ + unsigned int count = [self count]; + const char *ce = [self contentType]; + const char *ke = [self keyType]; + void archiveKeyAndContent(elt key, elt content) + { + [aCoder encodeValueOfType:ke + at:elt_get_ptr_to_member(ke, &key) + withName:"KeyedCollection key element"]; + [aCoder encodeValueOfType:ce + at:elt_get_ptr_to_member(ce, &content) + withName:"KeyedCollection content element"]; + } + + [aCoder encodeValueOfSimpleType:@encode(unsigned) + at:&count + withName:"Collection element count"]; + [self withKeyElementsAndContentElementsCall:archiveKeyAndContent]; +} + +- (void) _decodeContentsWithCoder: (Coder*)aCoder +{ + unsigned int count, i; + elt newKey, newContent; + const char *ce = [self contentType]; + const char *ke = [self keyType]; + + [aCoder decodeValueOfSimpleType:@encode(unsigned) + at:&count + withName:NULL]; + for (i = 0; i < count; i++) + { + [aCoder decodeValueOfType:ke + at:elt_get_ptr_to_member(ke, &newKey) + withName:NULL]; + [aCoder decodeValueOfType:ce + at:elt_get_ptr_to_member(ce, &newContent) + withName:NULL]; + [self putElement:newContent atKey:newKey]; + } +} + + +- _writeContents: (TypedStream*)aStream +{ + unsigned int count = [self count]; + const char *ce = [self contentType]; + const char *ke = [self keyType]; + void archiveKeyAndContent(elt key, elt content) + { + objc_write_types(aStream, ke, + elt_get_ptr_to_member(ke, &key)); + objc_write_types(aStream, ce, + elt_get_ptr_to_member(ce, &content)); + } + + objc_write_type(aStream, @encode(unsigned int), &count); + [self withKeyElementsAndContentElementsCall:archiveKeyAndContent]; + return self; +} + +- _readContents: (TypedStream*)aStream +{ + unsigned int count, i; + elt newKey, newContent; + const char *ce = [self contentType]; + const char *ke = [self keyType]; + + objc_read_type(aStream, @encode(unsigned int), &count); + for (i = 0; i < count; i++) + { + objc_read_types(aStream, ke, + elt_get_ptr_to_member(ke, &newKey)); + objc_read_types(aStream, ce, + elt_get_ptr_to_member(ce, &newContent)); + [self putElement:newContent atKey:newKey]; + } + return self; +} + +@end diff --git a/Source/LinkedList.m b/Source/LinkedList.m new file mode 100644 index 000000000..c2d65f6aa --- /dev/null +++ b/Source/LinkedList.m @@ -0,0 +1,321 @@ +/* Implementation for Objective-C LinkedList collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +@implementation LinkedList + ++ initialize +{ + if (self == [LinkedList class]) + [self setVersion:0]; /* beta release */ + return self; +} + +/* This is the designated initializer of this class */ +- init +{ + [super initWithType:@encode(id)]; + _count = 0; + _first_link = nil; + return self; +} + +/* Archiving must mimic the above designated initializer */ + ++ _newCollectionWithCoder: (Coder*)aCoder +{ + LinkedList *n; + n = [super _newCollectionWithCoder:aCoder]; + n->_count = 0; + n->_first_link = nil; + return n; +} + +- (void) _encodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder startEncodingInterconnectedObjects]; + [super _encodeContentsWithCoder:aCoder]; + [aCoder finishEncodingInterconnectedObjects]; +} + +- (void) _decodeContentsWithCoder: (Coder*)aCoder +{ + [aCoder startDecodingInterconnectedObjects]; + [super _decodeContentsWithCoder:aCoder]; + [aCoder finishDecodingInterconnectedObjects]; +} + +- _readInit: (TypedStream*)aStream +{ + [super _readInit:aStream]; + _count = 0; + _first_link = nil; + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + LinkedList *copy = [super emptyCopy]; + copy->_count = 0; + copy->_first_link = nil; + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + _count = 0; + _first_link = nil; + return self; +} + +/* Override the designated initializer for our superclass IndexedCollection + to make sure we have object values. */ +- initWithType: (const char *)contentEncoding +{ + if (!ENCODING_IS_OBJECT(contentEncoding)) + [self error:"LinkedList contents must be objects conforming to " + " protocol"]; + [self init]; + return self; +} + +/* These next four methods are the only ones that change the values of + the instance variables _count, _first_link, except for + "-initDescription:". */ + +- (elt) removeElement: (elt)oldElement +{ + if (_first_link == oldElement.id_u) + { + if (_count > 1) + _first_link = [oldElement.id_u nextLink]; + else + _first_link = nil; + } + [[oldElement.id_u nextLink] setPrevLink:[oldElement.id_u prevLink]]; + [[oldElement.id_u prevLink] setNextLink:[oldElement.id_u nextLink]]; + _count--; + return oldElement; +} + +- insertElement: (elt)newElement after: (elt)oldElement +{ + if (_count == 0) + { + /* link to self */ + _first_link = newElement.id_u; + [newElement.id_u setNextLink:newElement.id_u]; + [newElement.id_u setPrevLink:newElement.id_u]; + } + else + { + [newElement.id_u setNextLink:[oldElement.id_u nextLink]]; + [newElement.id_u setPrevLink:oldElement.id_u]; + [[oldElement.id_u nextLink] setPrevLink:newElement.id_u]; + [oldElement.id_u setNextLink:newElement.id_u]; + } + _count++; + return self; +} + +- insertElement: (elt)newElement before: (elt)oldElement +{ + if (oldElement.id_u == _first_link) + _first_link = newElement.id_u; + if (_count == 0) + { + /* Link to self */ + [newElement.id_u setNextLink:newElement.id_u]; + [newElement.id_u setPrevLink:newElement.id_u]; + } + else + { + [newElement.id_u setPrevLink:[oldElement.id_u prevLink]]; + [newElement.id_u setNextLink:oldElement.id_u]; + [[oldElement.id_u prevLink] setNextLink:newElement.id_u]; + [oldElement.id_u setPrevLink:newElement.id_u]; + } + _count++; + return self; +} + +- (elt) replaceElement: (elt)oldElement with: (elt)newElement +{ + if (oldElement.id_u == _first_link) + _first_link = newElement.id_u; + [newElement.id_u setNextLink:[oldElement.id_u nextLink]]; + [newElement.id_u setPrevLink:[oldElement.id_u prevLink]]; + [[oldElement.id_u prevLink] setNextLink:newElement.id_u]; + [[oldElement.id_u nextLink] setPrevLink:newElement.id_u]; + return oldElement; +} + +/* End of methods that change the instance variables. */ + + +- appendElement: (elt)newElement +{ + if (_count) + [self insertElement:newElement after:[self lastElement]]; + else + [self insertElement:newElement after:nil]; + return self; +} + +- prependElement: (elt)newElement +{ + [self insertElement:newElement before:_first_link]; + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, (_count+1)); + if (index == _count) + [self insertElement:newElement after:[self lastElement]]; + else + [self insertElement:newElement before:[self elementAtIndex:index]]; + return self; +} + +- (elt) removeElementAtIndex: (unsigned)index +{ + CHECK_INDEX_RANGE_ERROR(index, _count); + return [self removeElement:[self elementAtIndex:index]]; +} + +- (elt) elementAtIndex: (unsigned)index +{ + id aLink; + + CHECK_INDEX_RANGE_ERROR(index, _count); + if (index < _count / 2) + for (aLink = _first_link; + index; + aLink = [aLink nextLink], index--) + ; + else + for (aLink = [_first_link prevLink], index = _count - index - 1; + index; + aLink = [aLink prevLink], index--) + ; + return aLink; +} + +- (elt) firstElement +{ + return _first_link; +} + +- (elt) lastElement +{ + if (_count) + return [_first_link prevLink]; + else + return NO_ELEMENT_FOUND_ERROR(); +} + +- (elt) successorOfElement: (elt)oldElement +{ + id nextElement = [oldElement.id_u nextLink]; + if (_first_link == nextElement) + return nil; + else + return (elt)nextElement; +} + +- (elt) predecessorOfElement: (elt)oldElement +{ + if (_first_link == oldElement.id_u) + return nil; + else + return (elt)[oldElement.id_u prevLink]; +} + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + if (*enumState == _first_link) + return NO; + else if (!(*enumState)) + *enumState = _first_link; + *anElementPtr = *enumState; + *enumState = [(id)(*enumState) nextLink]; + return YES; +} + +- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + if (*enumState == _first_link) + return NO; + if (!(*enumState)) + *enumState = _first_link; + *enumState = [(id)(*enumState) prevLink]; + *anElementPtr = *enumState; + return YES; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + id link; + unsigned i; + + for (link = _first_link, i = 0; + *flag && i < _count; + link = [link nextLink], i++) + { + (*aFunc)(link); + } + return self; +} + +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + id link; + unsigned i; + + if (!_first_link) + return self; + for (link = [_first_link prevLink], i = 0; + *flag && i < _count; + link = [link prevLink], i++) + { + (*aFunc)(link); + } + return self; +} + + +- (unsigned) count +{ + return _count; +} + +@end + + + diff --git a/Source/LinkedListEltNode.m b/Source/LinkedListEltNode.m new file mode 100644 index 000000000..08144629c --- /dev/null +++ b/Source/LinkedListEltNode.m @@ -0,0 +1,39 @@ +/* Implementation for Objective-C LinkedListEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation LinkedListEltNode + ++ initialize +{ + if (self == [LinkedListEltNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +#include + +@end + diff --git a/Source/LinkedListNode.m b/Source/LinkedListNode.m new file mode 100644 index 000000000..8d9b639fc --- /dev/null +++ b/Source/LinkedListNode.m @@ -0,0 +1,97 @@ +/* Implementation for Objective-C LinkedListNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation LinkedListNode + ++ initialize +{ + if (self == [LinkedListNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- init +{ + [super init]; + _next = _prev = nil; + return self; +} + +- (void) encodeWithCoder: (Coder*)aCoder +{ + [super encodeWithCoder:aCoder]; + [aCoder encodeObjectReference:_next withName:"Next LinkedList Node"]; + [aCoder encodeObjectReference:_prev withName:"Prev LinkedList Node"]; +} + ++ newWithCoder: (Coder*)aCoder +{ + LinkedListNode *n = [super newWithCoder:aCoder]; + [aCoder decodeObjectAt:&(n->_next) withName:NULL]; + [aCoder decodeObjectAt:&(n->_prev) withName:NULL]; + return n; +} + +- write: (TypedStream*)aStream +{ + [super write:aStream]; + objc_write_object_reference(aStream, _next); + objc_write_object_reference(aStream, _prev); + return self; +} + +- read: (TypedStream*)aStream +{ + [super read:aStream]; + objc_read_object(aStream, &_next); + objc_read_object(aStream, &_prev); + return self; +} + +- (id ) nextLink +{ + return _next; +} + +- (id ) prevLink +{ + return _prev; +} + +- setNextLink: (id )aLink +{ + _next = aLink; + return self; +} + +- setPrevLink: (id )aLink +{ + _prev = aLink; + return self; +} + +@end + diff --git a/Source/List.m b/Source/List.m new file mode 100644 index 000000000..90d08d597 --- /dev/null +++ b/Source/List.m @@ -0,0 +1,367 @@ +/* Implementation of Objective-C NeXT-compatible List object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + This file is part of the GNU Objective C Class Library. + + Written by: R. Andrew McCallum + Date: May 1993 + + 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 + +/* Change this #define to 0 if you want -makeObjectsPerform: and + -makeObjectsPerform:with: to access content objects in order + from lower indices to higher indices. + If you want the NeXTSTEP behavior, leave the #define as 1. */ +#define LIST_PERFORM_REVERSE_ORDER_DEFAULT 1 + +#define LIST_GROW_FACTOR 2 + +#if !defined(NX_MALLOC) +#define NX_MALLOC(VAR,TYPE,NUM ) \ + ((VAR) = (TYPE *) malloc((unsigned)(NUM)*sizeof(TYPE))) +#endif +#if !defined(NX_REALLOC) +#define NX_REALLOC(VAR,TYPE,NUM ) \ + ((VAR) = (TYPE *) realloc((VAR), (unsigned)(NUM)*sizeof(TYPE))) +#endif +#if !defined(NX_FREE) +#define NX_FREE(VAR) free(VAR) +#endif + +/* memcpy() is a gcc builtin */ + + +/* Do this before adding an element */ +static inline void +incrementCount(List *self) +{ + (self->numElements)++; + if (self->numElements >= self->maxElements) + { + [self setAvailableCapacity:(self->numElements) * LIST_GROW_FACTOR]; + } +} + +/* Do this after removing an element */ +static inline void +decrementCount(List *self) +{ + (self->numElements)--; + if (self->numElements < (self->maxElements) / LIST_GROW_FACTOR) + { + [self setAvailableCapacity:(self->maxElements) / LIST_GROW_FACTOR]; + } +} + +@implementation List + ++ initialize +{ + if (self == [List class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// INITIALIZING, FREEING; + +- initCount:(unsigned)numSlots; +{ + [super init]; + numElements = 0; + maxElements = numSlots; + NX_MALLOC(dataPtr, id, maxElements); + return self; +} + +- init +{ + return [self initCount:2]; +} + + +- free +{ + if (dataPtr) + NX_FREE(dataPtr); + return [super free]; +} + +- freeObjects +{ + [self makeObjectsPerform:@selector(free)]; + [self empty]; + return self; +} + +// COPYING; + +- copy +{ + return [self shallowCopy]; +} + +- shallowCopy +{ + List *c = [super shallowCopy]; + NX_MALLOC(c->dataPtr, id, maxElements); + memcpy(c->dataPtr, dataPtr, numElements * sizeof(id *)); + return c; +} + +- deepen +{ + int i; + + for (i = 0; i < numElements; i++) + { + dataPtr[i] = [dataPtr[i] deepCopy]; + } + return self; +} + +// COMPARING TWO LISTS; + +- (BOOL)isEqual: anObject +{ + int i; + + if ( (![anObject isKindOf:[List class]]) + || ([self count] != [anObject count])) + return NO; + for (i = 0; i < numElements; i++) + /* NeXT documentation says to compare id's. */ + if ( dataPtr[i] != [anObject objectAt:i] ) + return NO; + return YES; +} + +// MANAGING THE STORAGE CAPACITY; + +- (unsigned)capacity +{ + return maxElements; +} + +- setAvailableCapacity:(unsigned)numSlots +{ + if (numSlots > numElements) + { + maxElements = numSlots; + NX_REALLOC(dataPtr, id, maxElements); + return self; + } + return nil; +} + + +/* Manipulating objects by index */ + +#define CHECK_INDEX(IND) if ((IND) >= numElements) return nil +#define CHECK_OBJECT(OBJ) if (!(OBJ)) return nil + +- (unsigned)count +{ + return numElements; +} + +- objectAt:(unsigned)index +{ + CHECK_INDEX(index); + return dataPtr[index]; +} + +- lastObject +{ + if (numElements) + return dataPtr[numElements-1]; + else + return nil; +} + +- addObject:anObject +{ + [self insertObject:anObject at:numElements]; + return self; +} + +- insertObject:anObject at:(unsigned)index +{ + int i; + + if (index > 0) { + CHECK_INDEX(index-1); + } + CHECK_OBJECT(anObject); + incrementCount(self); + for (i = numElements-1; i > index; i--) + dataPtr[i] = dataPtr[i-1]; + dataPtr[i] = anObject; + return self; +} + +- removeObjectAt:(unsigned)index +{ + id oldObject; + int i; + + CHECK_INDEX(index); + oldObject = dataPtr[index]; + for (i = index; i < numElements-1; i++) + dataPtr[i] = dataPtr[i+1]; + decrementCount(self); + return oldObject; +} + +- removeLastObject +{ + if (numElements) + return [self removeObjectAt:numElements-1]; + return nil; +} + +- replaceObjectAt:(unsigned)index with:newObject +{ + id oldObject; + + CHECK_INDEX(index); + CHECK_OBJECT(newObject); + oldObject = dataPtr[index]; + dataPtr[index] = newObject; + return oldObject; +} + +/* Inefficient to send objectAt: each time, but it handles subclasses + of List nicely. */ +- appendList: (List *)otherList +{ + int i, c; + + c = [otherList count]; + /* Should we do something like this for efficiency? + [self setCapacity:numElements+c]; */ + for (i = 0; i < c; i++) + [self addObject:[otherList objectAt:i]]; + return self; +} + +/* Manipulating objects by id */ + +- (unsigned) indexOf:anObject +{ + int i; + + for (i = 0; i < numElements; i++) + if ([dataPtr[i] isEqual:anObject]) + return i; + return NX_NOT_IN_LIST; +} + +- addObjectIfAbsent:anObject +{ + CHECK_OBJECT(anObject); + if ([self indexOf:anObject] == NX_NOT_IN_LIST) + [self addObject:anObject]; + return self; +} + +- removeObject:anObject +{ + CHECK_OBJECT(anObject); + return [self removeObjectAt:[self indexOf:anObject]]; +} + +- replaceObject:anObject with:newObject +{ + return [self replaceObjectAt:[self indexOf:anObject] + with:newObject]; +} + +/* Emptying the list */ + +- empty +{ + int i; + + for (i = 0; i < numElements; i++) + dataPtr[i] = nil; + numElements = 0; + return self; +} + +/* Archiving */ + +- write: (TypedStream*)aStream +{ + [super write: aStream]; + objc_write_types (aStream, "II", &numElements, &maxElements); + objc_write_array (aStream, "@", numElements, dataPtr); + return self; +} + +- read: (TypedStream*)aStream +{ + [super read: aStream]; + objc_read_types (aStream, "II", &numElements, &maxElements); + NX_MALLOC(dataPtr, id, maxElements); + objc_read_array (aStream, "@", numElements, dataPtr); + return self; +} + +/* Sending messages to elements of the list */ + +- makeObjectsPerform:(SEL)aSel +{ + int i; + + /* For better interaction with List subclasses, we could use + objectAt: instead of accessing dataPtr directly. */ +#if (LIST_PERFORM_REVERSE_ORDER_DEFAULT) + for (i = numElements-1; i >= 0; i--) + [dataPtr[i] perform:aSel]; +#else + for (i = 0; i < numElements; i++) + [dataPtr[i] perform:aSel]; +#endif /* LIST_PERFORM_REVERSE_ORDER_DEFAULT */ + return self; +} + +- makeObjectsPerform:(SEL)aSel with:anObject +{ + int i; + + /* For better interaction with List subclasses, we could use + objectAt: instead of accessing dataPtr directly. */ +#if (LIST_PERFORM_REVERSE_ORDER_DEFAULT) + for (i = numElements-1; i >= 0; i--) + [dataPtr[i] perform:aSel with:anObject]; +#else + for (i = 0; i < numElements; i++) + [dataPtr[i] perform:aSel with:anObject]; +#endif /* LIST_PERFORM_REVERSE_ORDER_DEFAULT */ + return self; +} + + +/* Old-style creation */ + ++ newCount:(unsigned)numSlots +{ + return [[self alloc] initCount:numSlots]; +} + +@end diff --git a/Source/Lock.m b/Source/Lock.m new file mode 100644 index 000000000..b55126818 --- /dev/null +++ b/Source/Lock.m @@ -0,0 +1,46 @@ +/* Implementation of Objective-C Lock object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +/* It doesn't make sense to implement this until + we get a thread-safe runtime. */ + +@implementation Lock + +- (void) lock +{ + return; +} + +- (void) unlock +{ + return; +} + +- (BOOL) tryLock +{ + return YES; +} + +@end diff --git a/Source/Magnitude.m b/Source/Magnitude.m new file mode 100644 index 000000000..4b530ff4d --- /dev/null +++ b/Source/Magnitude.m @@ -0,0 +1,95 @@ +/* Implementation for Objective-C Magnitude object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +/* These methods accesses no instance variables. It is exactly the kind + of thing that should be a "behavior" associated with a protocol. + i.e. #3 on Steve Naroff's wish list. */ + +@implementation Magnitude + +/* - (int) compare: anObject; is inherited from Object */ + +- (BOOL) greaterThan: anObject +{ + if ([self compare:anObject] > 0) + return YES; + else + return NO; +} + +- (BOOL) greaterThanOrEqual: anObject +{ + if ([self compare:anObject] >= 0) + return YES; + else + return NO; +} + + +- (BOOL) lessThan: anObject +{ + if ([self compare:anObject] < 0) + return YES; + else + return NO; +} + +- (BOOL) lessThanOrEqual: anObject +{ + if ([self compare:anObject] <= 0) + return YES; + else + return NO; +} + + +- (BOOL) between: firstObject and: secondObject +{ + if ([self compare:firstObject] >= 0 + && [self compare:secondObject] <= 0) + return YES; + else + return NO; +} + + +- maximum: anObject +{ + if ([self compare:anObject] >= 0) + return self; + else + return anObject; +} + +- minimum: anObject +{ + if ([self compare:anObject] <= 0) + return self; + else + return anObject; +} + +@end diff --git a/Source/MappedCollector.m b/Source/MappedCollector.m new file mode 100644 index 000000000..2a7d365af --- /dev/null +++ b/Source/MappedCollector.m @@ -0,0 +1,166 @@ +/* Implementation for Objective-C MappedCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +@implementation MappedCollector + +/* This is the designated initializer for this class */ +- initCollection: (id )aDomain + map: (id )aMap +{ + if (strcmp([aMap contentType], [aDomain keyType])) + [self error:"map's contents are not the same as domain's keys"]; + [super initWithType:[aDomain contentType] + keyType:[aMap keyType]]; + _map = aMap; + _domain = aDomain; + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- _writeInit: (TypedStream*)aStream +{ + [super _writeInit: aStream]; + objc_write_object(aStream, _map); + objc_write_object(aStream, _domain); + return self; +} + +- _readInit: (TypedStream*)aStream +{ + [super _readInit: aStream]; + objc_read_object(aStream, &_map); + objc_read_object(aStream, &_domain); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + MappedCollector *copy = [super emptyCopy]; + copy->_map = [_map emptyCopy]; + copy->_domain = [_domain emptyCopy]; + return copy; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + [_domain empty]; + return self; +} + +- (const char *) contentType +{ + return [_domain contentType]; +} + +- (const char *) keyType +{ + return [_map keyType]; +} + +- (int(*)(elt,elt)) comparisonFunction +{ + return [_domain comparisonFunction]; +} + +- (elt) elementAtKey: (elt)aKey +{ + return [_domain elementAtKey:[_map elementAtKey:aKey]]; +} + +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newElement +{ + return [_domain replaceElementAtKey:[_map elementAtKey:aKey] + with:newElement]; +} + +- putElement: (elt)newElement atKey: (elt)aKey +{ + return [_domain putElement:newElement + atKey:[_map elementAtKey:aKey]]; +} + +- (elt) removeElementAtKey: (elt)aKey +{ + return [_domain removeElementAtKey:[_map elementAtKey:aKey]]; +} + +- (BOOL) includesKey: (elt)aKey +{ + return [_domain includesKey:[_map elementAtKey:aKey]]; +} + +- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc + whileTrue: (BOOL *)flag +{ + void doIt(elt e) + { + elt domainKey = [_map elementAtKey:e]; + if ([_domain includesKey:domainKey]) + (*aFunc)(e, [_domain elementAtKey:domainKey]); + } + [_map withKeyElementsCall:doIt]; + return self; +} + +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState; +{ + BOOL ret; + elt mapContent; + elt domainKey; + + while ((ret = [_map getNextKey:aKeyPtr content:&mapContent + withEnumState:enumState]) + && + (![_domain includesKey:(domainKey = [_map elementAtKey:*aKeyPtr])])) + ; + if (!ret) + return NO; + *anElementPtr = [_domain elementAtKey:domainKey]; + return YES; +} + +- species +{ + return [Dictionary class]; +} + +@end diff --git a/Source/MemoryStream.m b/Source/MemoryStream.m new file mode 100644 index 000000000..0b3559d27 --- /dev/null +++ b/Source/MemoryStream.m @@ -0,0 +1,302 @@ +/* Implementation of GNU Objective C memory stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/* Deal with memchr: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + +/* This could be done with a set of classes instead. */ +enum {MALLOC_MEMORY_STREAM = 0, OBSTACK_MEMORY_STREAM, VM_MEMORY_STREAM}; + +#define DEFAULT_MEMORY_STREAM_SIZE 64 + +extern int +objects_vscanf (void *stream, + int (*inchar_func)(void*), + void (*unchar_func)(void*,int), + const char *format, va_list argptr); + +static BOOL debug_memory_stream = YES; + +/* A pretty stupid implementation based on realloc(), but it works for now. */ + +@implementation MemoryStream + +/* xxx This interface will change */ +- _initOnMallocBuffer: (char*)b + size: (unsigned)s /* size of malloc'ed buffer */ + eofPosition: (unsigned)l /* length of buffer with data for reading */ + prefix: (unsigned)p /* never read/write before this position */ + position: (unsigned)i /* current position for reading/writing */ +{ + [super initWithMode:STREAM_READWRITE]; + buffer = b; + size = s; + prefix = p; + position = i; + eofPosition = l; + type = MALLOC_MEMORY_STREAM; + return self; +} + +- initWithSize: (unsigned)s + prefix: (unsigned)p + position: (unsigned)i +{ + char *b; + OBJC_MALLOC(b, char, s); + return [self _initOnMallocBuffer:b size:s eofPosition:i + prefix:p position:i]; +} + +/* xxx Put mode in here */ +- initWithSize: (unsigned)s +{ + return [self initWithSize:s prefix:0 position:0]; +} + +- initWithMode: (int)m +{ + return [self initWithSize: DEFAULT_MEMORY_STREAM_SIZE]; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- (int) writeBytes: (const void*)b length: (int)l +{ + if (prefix+position+l > size) + { + size *= 2; + buffer = (*objc_realloc)(buffer, size); + } + memcpy(buffer+prefix+position, b, l); + position += l; + if (position > eofPosition) + eofPosition = position; + return l; +} + +- (int) readBytes: (void*)b length: (int)l +{ + if (position+l > eofPosition) + l = eofPosition-position; + memcpy(b, buffer+prefix+position, l); + position += l; + return l; +} + +- (void) writeLine: (const char *)l +{ + [self writeBytes:l length:strlen(l)]; + [self writeBytes:"\n" length:1]; +} + +/* This malloc's the buffer pointed to by the return value */ +- (char *) readLine +{ + char *nl = memchr(buffer+prefix+position, '\n', eofPosition-position); + char *ret = NULL; + if (nl) + { + int len = nl-buffer-prefix-position; + ret = (*objc_malloc)(len+1); + strncpy(ret, buffer+prefix+position, len); + ret[len] = '\0'; + position += len+1; + } + return ret; +} + +/* Making these nested functions (which is what I'd like to do) is + crashing the va_arg stuff in vscanf(). Why? */ +#define MS ((MemoryStream*)s) + +int outchar_func(void *s, int c) +{ + if (MS->prefix + MS->position >= MS->size) + return EOF; + MS->buffer[MS->prefix + MS->position++] = (char)c; + return 1; +} + +int inchar_func(void *s) +{ + if (MS->prefix + MS->position >= MS->size) + return EOF; + return (int) MS->buffer[MS->prefix + MS->position++]; +} + +void unchar_func(void *s, int c) +{ + if (MS->position > 0) + MS->position--; + MS->buffer[MS->prefix + MS->position] = (char)c; +} + +#if HAVE_VSPRINTF +- (int) writeFormat: (const char *)format, ... +{ + int ret; + va_list ap; + + /* xxx Using this ugliness we at least let ourselves safely print + formatted strings up to 128 bytes long. + It's digusting, though, and we need to fix it. + Using GNU stdio streams would do the trick. + */ + if (size - (prefix + position) < 128) + [self setStreamBufferSize:size*2]; + + va_start(ap, format); + ret = vsprintf(buffer+prefix+position, format, ap); + va_end(ap); + position += ret; + /* xxx Make sure we didn't overrun our buffer. + As per above kludge, this would happen if we happen to have more than + 128 bytes left in the buffer and we try to write a string longer than + the num bytes left in the buffer. */ + assert(prefix + position <= size); + if (position > eofPosition) + eofPosition = position; + if (debug_memory_stream) + { + *(buffer+prefix+position) = '\0'; + fprintf(stderr, "%s\n", buffer+prefix); + } + return ret; +} +#endif + +- (int) readFormat: (const char *)format, ... +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = objects_vscanf(self, inchar_func, unchar_func, format, ap); + va_end(ap); + return ret; +} + +- (void) flushStream +{ + /* Nothing needed */ +} + +- (void) setStreamPosition: (unsigned)i +{ + position = i; +} + +- (unsigned) streamPosition +{ + return position; +} + +- free +{ + OBJC_FREE(buffer); + return [super free]; +} + +- (BOOL) streamEof +{ + if (position == eofPosition) + return YES; + else + return NO; +} + +- (unsigned) streamBufferSize +{ + return size; +} + +- (char *) streamBuffer +{ + return buffer; +} + +- (unsigned) prefix +{ + return prefix; +} + +- (void) setStreamBufferSize: (unsigned)s +{ + if (s > prefix + eofPosition) + { + buffer = (*objc_realloc)(buffer, s); + size = s; + } +} + +- (unsigned) streamEofPosition +{ + return eofPosition; +} + +- (void) setStreamEofPosition: (unsigned)i +{ + if (i < size) + eofPosition = i; +} + +- (unsigned) streamPrefix +{ + return prefix; +} + +- (unsigned) streamBufferLength +{ + return prefix + eofPosition; +} +@end diff --git a/Source/NSZone.c b/Source/NSZone.c new file mode 100644 index 000000000..612820787 --- /dev/null +++ b/Source/NSZone.c @@ -0,0 +1,46 @@ +#include + +NXZone *NXDefaultMallocZone(void) +{ + return NX_NOZONE; +} + +NXZone *NXCreateZone(size_t startSize, size_t granularity, int canFree) +{ + return NX_NOZONE; +} + +NXZone *NXCreateChildZone(NXZone *parentZone, size_t startSize, size_t granularity, int canFree) +{ + return NX_NOZONE; +} + +void NXMergeZone(NXZone *zonep) +{ + return; +} + +void *NXZoneCalloc(NXZone *zonep, size_t numElems, size_t byteSize) +{ + return 0; +} + +NXZone *NXZoneFromPtr(void *ptr) +{ + return NX_NOZONE; +} + +void NXZonePtrInfo(void *ptr) +{ + return; +} + +int NXMallocCheck(void) +{ + return 1; +} + +void NXNameZone(NXZone *z, const char *name) +{ + return; +} diff --git a/Source/NXStringTable.m b/Source/NXStringTable.m new file mode 100644 index 000000000..ec00db75a --- /dev/null +++ b/Source/NXStringTable.m @@ -0,0 +1,151 @@ +/* Implementation for Objective C NeXT-compatible NXStringTable object + Copyright (C) 1993 Free Software Foundation, Inc. + + Written by: Adam Fedor + + This file is part of the GNU Objective-C Collection 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + StringTable - Hash table for strings in the NeXT StringTable style + + $Id$ + + TODO: Should I reject duplicate keys on readFromStream? + the real MAX_STRINGTABLE_LENGTH is in NXStringTable.l, even though + it also appears in StringTable.h +*/ + +#include +#include +#include +#include + +char * +CopyStringBuffer(const char *buf) +{ + char *out; + if (!buf) + return NULL; + OBJC_MALLOC(out, char, strlen(buf)+1); + if (out) + strcpy(out, buf); + return out; +} + +/* table_scan is a lexical parser created using flex. It parses a string + table and returns (1) every time it finds a token (the token is stored + in *str. It returns (-1) on an error or (0) when finished. Tokens are + guaranteed to alternate between Keys and Values. +*/ +#if HAVE_FLEX +extern int NXtable_scan(FILE *in_stream, FILE *out_stream, const char **str); +#else +/* Variables to export to yylex */ +FILE *NXscan_in; +FILE *NXscan_out; +char *NXscan_string; +#endif + +@implementation NXStringTable + +- init +{ + return [super initKeyDesc: "*" valueDesc: "*"]; +} + +- (const char *)valueForStringKey:(const char *)aString +{ + return [super valueForKey:aString]; +} + +- readFromStream:(FILE *)stream +{ + const char *str; + char *key = 0, *value; + int status; + BOOL gotKey = NO; + +#if HAVE_FLEX + status = NXtable_scan(stream, stderr, &str); +#else + NXscan_in = stream; + NXscan_out = stderr; + status = NXlex_lex(); + str = NXscan_string; +#endif + while (status > 0) { + if (gotKey) { + value = CopyStringBuffer(str); + [super insertKey:key value:value]; + } else + key = CopyStringBuffer(str); + gotKey = ~gotKey; +#if HAVE_FLEX + status = NXtable_scan(stream, stderr, &str); +#else + status = NXlex_lex(); +#endif + } + if (gotKey) { + OBJC_FREE(key); + return nil; + } + + return (status >= 0) ? self : nil; +} + +- readFromFile:(const char *)fileName +{ + FILE *stream; + if ((stream = fopen(fileName, "r")) == NULL) { + perror("Error (NXStringTable)"); + return nil; + } + [self readFromStream:stream]; + fclose(stream); + return self; +} + +- writeToStream:(FILE *)stream +{ + const char *key; + char *value; + NXHashState state = [super initState]; + while ([super nextState: &state + key: (const void **)&key + value: (void **)&value]) + fprintf(stream, "\"%s\" = \"%s\";\n", key, value); + + return self; +} + +- writeToFile:(const char *)fileName +{ + FILE *stream; + if ((stream = fopen(fileName, "w")) == NULL) { + perror("Error (NXStringTable)"); + return nil; + } + [self writeToStream:stream]; + fclose(stream); + return self; +} + +@end + + diff --git a/Source/NXStringTable_scan.l b/Source/NXStringTable_scan.l new file mode 100644 index 000000000..d6bcb93ee --- /dev/null +++ b/Source/NXStringTable_scan.l @@ -0,0 +1,184 @@ +%{ + +#ifdef HAVE_FLEX +#define YY_DECL int NXtable_scan(FILE *NXscan_in, \ + FILE *NXscan_out, const char **buffer) +#endif +#define MAX_STRINGTABLE_LENGTH 1024 +#define KEY 1 +#define VALUE 2 + +#define yyterminate() {got = 0; line = 1; return YY_NULL;} +#define return_err() {got = 0; line = 1; return -1;} +#define return_ok() {return 1;} + +%} + +ESCAPES [abfnrtv] + +%s parse comment token + +%% + /* Lexical initialization - This gets executed before any analysis */ + char string_buf[MAX_STRINGTABLE_LENGTH]; + char *string_buf_ptr; + static int got; /* Holds the type of token we just got */ + static int line; + #ifndef HAVE_FLEX + extern FILE *NXscan_in; + extern FILE *NXscan_out; + extern char *NXscan_string; + #endif + if (yyin != NXscan_in) { /* Reset */ + got = 0; + line= 1; + yyin = NXscan_in; + } + yyout = NXscan_out; + #ifdef HAVE_FLEX + *buffer = string_buf; + #else + NXscan_string = string_buf; + #endif + BEGIN(parse); + +"/*" BEGIN(comment); + +[^*\n]* /* eat anything that's not a '*' */; +"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */; +\n line++; +"*"+"/" BEGIN(parse); +<> { + /* error - unterminated comment */ + fprintf(stderr, "ERROR (NXStringTable): Unterminated comment\n"); + return_err(); + } + += { + if (!got) { + fprintf(stderr, "\nERROR (NXStringTable): Improper use of = (Expected a key, line %d)\n", line); + return_err(); + } + if (got == VALUE) { + fprintf(stderr, "\nERROR (NXStringTable): Improper use of = (Expected a ;, line %d)\n", line); + return_err(); + } + } + +; { + if (!got) { + fprintf(stderr, "\nERROR (NXStringTable): Improper use of ; (Expected a key, line %d)\n", line); + return_err(); + } + if (got == KEY) { + got = 0; + return_ok(); + } + got = 0; + } + +[ \t]* /* Eat up white space between tokens */; + +\n line++; + +\" {string_buf_ptr = string_buf; BEGIN(token);} + +[A-Za-z]* { + fprintf(stderr, "ERROR (NXStringTable): Extra characters in table (line %d)\n", line); + return_err(); + } + +\" { /* saw closing quote - all done */ + BEGIN(parse); + *string_buf_ptr = '\0'; + /* return string constant token type and + * value to parser + */ + got++; + if (got == KEY || got == VALUE) { + return_ok(); + } else { + fprintf(stderr, "ERROR (NXStringTable): Parse error, line %d \n", line); + return_err(); + } + } + +\n { + /* error - unterminated string constant */ + fprintf(stderr, "ERROR (NXStringTable): Unterminated string (line %d)\n", line); + return_err(); + } + +<> { + /* error - unterminated string constant */ + fprintf(stderr, "ERROR (NXStringTable): Unterminated string (line %d)\n", line); + return_err(); + } + +\\{ESCAPES} {*string_buf_ptr++='\\';*string_buf_ptr++ = yytext[1];} + +\\(.|\n) *string_buf_ptr++ = yytext[1]; + +[^\\\n\"]+ { + char *text_ptr = yytext; + if (!text_ptr) { + fprintf(stderr, "ERROR (NXStringTable): internal parse error\n"); + break; + } + while ( *text_ptr ) + *string_buf_ptr++ = *text_ptr++; + } + +%% + +int +yywrap() +{ + return 1; +} + +#ifdef NEED_MAIN +#ifndef HAVE_FLEX + FILE *NXscan_in; + FILE *NXscan_out; + char *NXscan_string; +#endif +int +main(int argc, char *argv[]) +{ + FILE *input; + const char *str; + int ok, value = 0; + + if (argc > 1) { + if ((input = fopen(argv[1], "r")) == NULL) { + fprintf(stderr, "Error: Couldn't open %s\n", argv[1]); + exit (1); + } + } else + exit(1); + +#ifdef HAVE_FLEX + ok = NXtable_scan( input, stdout, &str); +#else + NXscan_in = input; + NXscan_out = stdout; + ok = yylex(); + str = NXscan_string; +#endif + while (ok > 0) { + if (value) + printf("Value: %s\n", str); + else + printf("Key: %s\n", str); + value = ~value; +#ifdef HAVE_FLEX + ok = NXtable_scan( input, stdout, &str); +#else + ok = yylex(); +#endif + } + + return 0; +} +#endif diff --git a/Source/Port.m b/Source/Port.m new file mode 100644 index 000000000..c50a4634c --- /dev/null +++ b/Source/Port.m @@ -0,0 +1,105 @@ +/* Implementation of abstract superclass port for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include /* for Coding protocol in Object category */ + +@implementation Port + ++ newRegisteredPortWithName: (const char *)n +{ + [self notImplemented:_cmd]; + return nil; +} + ++ newPortFromRegisterWithName: (const char *)n onHost: (const char *)host +{ + [self notImplemented:_cmd]; + return nil; +} + ++ newPort +{ + [self notImplemented:_cmd]; + return nil; +} + +/* These sending and receiving interfaces will change */ + +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*) remote + timeout: (int) milliseconds +{ + [self notImplemented:_cmd]; + return 0; +} + +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*) remote +{ + return [self sendPacket:b length:l toPort:remote timeout:-1]; +} + +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote + timeout: (int) milliseconds +{ + [self notImplemented:_cmd]; + return 0; +} + +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote +{ + return [self receivePacket:b length:l fromPort:remote timeout:-1]; +} + +- (BOOL) isSoft +{ + [self notImplemented:_cmd]; + return YES; +} + +- (BOOL) isEqual: anotherPort +{ + [self notImplemented:_cmd]; + return NO; +} + +- (unsigned) hash +{ + [self notImplemented:_cmd]; + return 0; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [super encodeWithCoder:anEncoder]; +} + ++ newWithCoder: (Coder*)aDecoder; +{ + return [super newWithCoder:aDecoder]; +} + +@end diff --git a/Source/Proxy.m b/Source/Proxy.m new file mode 100644 index 000000000..5f69b7fb6 --- /dev/null +++ b/Source/Proxy.m @@ -0,0 +1,381 @@ +/* Implementation of GNU Objective-C Proxy for remote object messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static BOOL debugProxies = NO; + +#if NeXT_runtime +static id tmp_kludge_protocol = nil; +#endif + +@implementation Proxy + +/* Required by NeXT runtime */ ++ initialize +{ + return self; +} + +#if NeXT_runtime ++ setProtocolForProxies: (Protocol*)p +{ + tmp_kludge_protocol = p; + return self; +} +#endif + ++ newForRemote: (unsigned)aTarget connection: (Connection*)c +{ + Proxy *newProxy; + + if ((newProxy = [c proxyForTarget:aTarget])) + return newProxy; + + newProxy = class_create_instance([Proxy class]); + newProxy->target = aTarget; + newProxy->connection = c; + newProxy->retain_count = 0; +#if NeXT_runtime + newProxy->_method_types = coll_hash_new(32, + elt_hash_void_ptr, + elt_compare_void_ptrs); + newProxy->protocol = nil; +#endif + + if (debugProxies) + printf("%s: proxy=0x%x name %u\n", + sel_get_name(_cmd), (unsigned)newProxy, newProxy->target); + + [c addProxy:newProxy]; + return newProxy; +} + +- notImplemented: (SEL)aSel +{ + [Object error:"Proxy notImplemented %s", sel_get_name(aSel)]; + return self; +} + +- self +{ + return self; +} + +#if NeXT_runtime ++ class +{ + return self; +} +#else ++ (Class*) class +{ + return (Class*)self; +} +#endif + +- invalidateProxy +{ + /* What should go here? */ + [connection removeProxy:self]; + return self; +} + +- (BOOL) isProxy +{ + return YES; +} + +- (void) encodeWithCoder: aRmc +{ + [[self classForConnectedCoder:aRmc] + encodeObject:self + withConnectedCoder:aRmc]; +} + +- classForConnectedCoder: aRmc; +{ + return object_get_class(self); +} + +static inline BOOL class_is_kind_of(CLASS self, CLASS aClassObject) +{ + CLASS class; + + for (class = self; class!=Nil; class = class_get_super_class(class)) + if (class==aClassObject) + return YES; + return NO; +} + ++ (void) encodeObject: anObject withConnectedCoder: aRmc +{ + unsigned aTarget; + BOOL willBeLocal; + assert([aRmc connection]); + if (class_is_kind_of(object_get_class(anObject), [Proxy class])) + { + /* anObject is a Proxy, or a Proxy subclass */ + aTarget = [anObject targetForProxy]; + if ([aRmc connection] == [anObject connectionForProxy]) + { + /* This proxy is local on the other side */ + willBeLocal = YES; + [aRmc encodeObjectBycopy:nil + withName:"Proxy is local on other side"]; + [aRmc encodeValueOfType:@encode(unsigned) + at:&aTarget + withName:"Object Proxy target"]; + [aRmc encodeValueOfType:@encode(BOOL) + at:&willBeLocal + withName:"Proxy willBeLocal"]; + } + else + { + /* This proxy will still be remote on the other side */ + id op = [[anObject connectionForProxy] outPort]; + willBeLocal = NO; + if (debugProxies) + fprintf(stderr, "Sending a triangle-connection proxy\n"); + /* It's remote here, so we need to tell other side where to form + triangle connection to */ + [aRmc encodeObjectBycopy:op + withName:"Proxy outPort"]; + [aRmc encodeValueOfType:@encode(unsigned) + at:&aTarget + withName:"Object Proxy target"]; + [aRmc encodeValueOfType:@encode(BOOL) + at:&willBeLocal + withName:"Proxy willBeLocal"]; + } + } + else + { + /* anObject is a non-Proxy object, e.g. Object */ + aTarget = PTR2LONG(anObject); + willBeLocal = NO; + /* Let the connection know that we're going, this also retains anObj */ + [[aRmc connection] addLocalObject:anObject]; + /* if nil port, other connection will use ConnectedCoder remotePort */ + [aRmc encodeObjectBycopy:nil + withName:"Proxy outPort == remotePort"]; + [aRmc encodeValueOfType:@encode(unsigned) + at:&aTarget + withName:"Object Proxy target"]; + [aRmc encodeValueOfType:@encode(BOOL) + at:&willBeLocal + withName:"Proxy willBeLocal"]; + } +} + ++ newWithCoder: aRmc +{ + unsigned new_target; + id newConnectionOutPort; + id c; + BOOL willBeLocal; + + if ([aRmc class] != [ConnectedCoder class]) + [self error:"Proxy objects only code with ConnectedCoder class"]; + assert([aRmc connection]); + [aRmc decodeObjectAt:&newConnectionOutPort withName:NULL]; + [aRmc decodeValueOfType:@encode(unsigned) + at:&new_target + withName:NULL]; + [aRmc decodeValueOfType:@encode(BOOL) + at:&willBeLocal + withName:NULL]; + if (newConnectionOutPort) + { + c = [Connection newForInPort:[[aRmc connection] inPort] + outPort:newConnectionOutPort + ancestorConnection:[aRmc connection]]; + } + else + { + c = [aRmc connection]; + } + + if (!willBeLocal) + { + if (debugProxies) + printf("returning remote Proxy, target=0x%x\n", new_target); + return [self newForRemote:new_target connection:c]; + } + else + { + assert(new_target); + if (debugProxies) + printf("returning local Object, target=0x%x\n", new_target); + /* xxx I should add something that makes sure this number is a + valid object address... offer a little protection against bad + clients. */ + return (id)new_target; + } +} + +- (unsigned) targetForProxy +{ + return target; +} + +- connectionForProxy +{ + return connection; +} + +- (const char *) selectorTypeForProxy: (SEL)selector +{ +#if NeXT_runtime +#if 0 + { + /* This is bogosity. You are required to include all methods sent + by any proxies in the protocol you pass to + +setProtocolForProxy: */ + struct objc_method_description *md; + md = [tmp_kludge_protocol descriptionForInstanceMethod:selector]; + if (md) + return md->types; + else + return NULL; + } +#elif 0 + { + /* This is disgusting bogosity. This only works if some other + class in the executable responds to this method. */ + /* xxx Look in the class hash table at all classes... */ + } +#else + { + elt e; + const char *t; + e = coll_hash_value_for_key(_method_types, selector); + t = e.char_ptr_u; + if (!t) + { + /* This isn't what we want, unless the remote machine has + the same architecture as us. */ + t = [connection _typeForSelector:selector remoteTarget:target]; + coll_hash_add(&_method_types, (void*)selector, t); + } + return t; + } +#endif /* 1 */ +#else + return sel_get_type(selector); +#endif +} + +/* xxx Clean up all this junk below */ + +- free +{ + [self release]; + return self; +} + +- (oneway void) release +{ + if (!retain_count--) + { + [self invalidateProxy]; + [self dealloc]; + } +} + +- retain +{ + retain_count++; + return self; +} + +- (void) dealloc +{ +#if NeXT_runtime + coll_hash_delete(_method_types); + object_dispose((Object*)self); +#else + object_dispose(self); +#endif +} + +- forward: (SEL)aSel :(arglist_t)frame +{ + if (debugProxies) + printf("Proxy forwarding %s\n", sel_get_name(aSel)); + return [connection connectionForward:self :aSel :frame]; +} + +/* We need to make an effort to pass errors back from the server + to the client */ + +- (unsigned) retainCount +{ + return retain_count; +} + +@end + +@implementation Object (ForProxy) +- (const char *) selectorTypeForProxy: (SEL)selector +{ +#if NeXT_runtime + { + Method m = class_get_instance_method(isa, selector); + if (m) + return m->method_types; + else + return NULL; + } +#else + return sel_get_type(selector); +#endif +} +@end + +#if 0 /* temporarily moved to Coder.m */ +@implementation Object (IsProxy) +- (BOOL) isProxy +{ + return NO; +} +@end +#endif + +@implementation Protocol (RemoteCoding) + +/* Perhaps Protocol's should be sent bycopy? */ + +- classForConnectedCoder: aRmc; +{ + return [Proxy class]; +} + +@end diff --git a/Source/Queue.m b/Source/Queue.m new file mode 100644 index 000000000..1af7ac1af --- /dev/null +++ b/Source/Queue.m @@ -0,0 +1,66 @@ +/* Implementation for Objective-C Queue object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation Queue + ++ initialize +{ + if (self == [Queue class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- enqueueElement: (elt)newElement +{ + [self prependElement:newElement]; + return self; +} + +/* Overriding */ +- addElement: (elt)anElement +{ + [self enqueueElement:anElement]; + return self; +} + +- (elt) dequeueElement +{ + return [self removeLastElement]; +} + +// OBJECT-COMPATIBLE MESSAGE NAMES; + +- enqueueObject: newObject +{ + return [self enqueueElement:newObject]; +} + +- dequeueObject +{ + return [self dequeueElement].id_u; +} + +@end diff --git a/Source/RBTree.m b/Source/RBTree.m new file mode 100644 index 000000000..17fdc64a7 --- /dev/null +++ b/Source/RBTree.m @@ -0,0 +1,278 @@ +/* Implementation for Objective-C Red-Black Tree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#define NODE_IS_RED(NODE) ([NODE isRed]) +#define NODE_IS_BLACK(NODE) (![NODE isRed]) + +/* sentinal */ +static id nilRBNode; + +@implementation RBTree + ++ initialize +{ + if (self == [RBTree class]) + { + [self setVersion:0]; /* beta release */ + nilRBNode = [[RBTreeNode alloc] init]; + [nilRBNode setBlack]; + } + return self; +} + +- nilNode +{ + return nilRBNode; +} + +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc +{ + id y; + + [super sortAddElement:newElement byCalling:aFunc]; + [newElement.id_u setRed]; + while (newElement.id_u != _contents_root + && [[newElement.id_u parentNode] isRed]) + { + if ([newElement.id_u parentNode] == + [[[newElement.id_u parentNode] parentNode] leftNode]) + { + y = [[[newElement.id_u parentNode] parentNode] leftNode]; + if ([y isRed]) + { + [[newElement.id_u parentNode] setBlack]; + [y setBlack]; + [[[newElement.id_u parentNode] parentNode] setRed]; + newElement.id_u = [[newElement.id_u parentNode] parentNode]; + } + else + { + if (newElement.id_u == [[newElement.id_u parentNode] rightNode]) + { + newElement.id_u = [newElement.id_u parentNode]; + [self leftRotateAroundNode:newElement.id_u]; + } + [[newElement.id_u parentNode] setBlack]; + [[[newElement.id_u parentNode] parentNode] setRed]; + [self rightRotateAroundNode: + [[newElement.id_u parentNode] parentNode]]; + } + } + else + { + y = [[[newElement.id_u parentNode] parentNode] rightNode]; + if ([y isRed]) + { + [[newElement.id_u parentNode] setBlack]; + [y setBlack]; + [[[newElement.id_u parentNode] parentNode] setRed]; + newElement.id_u = [[newElement.id_u parentNode] parentNode]; + } + else + { + if (newElement.id_u == [[newElement.id_u parentNode] leftNode]) + { + newElement.id_u = [newElement.id_u parentNode]; + [self rightRotateAroundNode:newElement.id_u]; + } + [[newElement.id_u parentNode] setBlack]; + [[[newElement.id_u parentNode] parentNode] setRed]; + [self leftRotateAroundNode: + [[newElement.id_u parentNode] parentNode]]; + } + } + } + [_contents_root setBlack]; + return self; +} + +- _RBTreeDeleteFixup: x +{ + id w; + + while (x != _contents_root && NODE_IS_BLACK(x)) + { + if (NODE_IS_LEFTCHILD(x)) + { + w = [[x parentNode] rightNode]; + if (NODE_IS_RED(w)) + { + [w setBlack]; + [[x parentNode] setRed]; + [self leftRotateAroundNode:[x parentNode]]; + w = [[x parentNode] rightNode]; + } + if (NODE_IS_BLACK([w leftNode]) && NODE_IS_BLACK([w rightNode])) + { + [w setRed]; + x = [x parentNode]; + } + else + { + if (NODE_IS_BLACK([w rightNode])) + { + [[w leftNode] setBlack]; + [w setRed]; + [self rightRotateAroundNode:w]; + w = [[x parentNode] rightNode]; + } + if (NODE_IS_BLACK([x parentNode])) + [w setBlack]; + else + [w setRed]; + [[x parentNode] setBlack]; + [[w rightNode] setBlack]; + [self leftRotateAroundNode:[x parentNode]]; + x = _contents_root; + } + } + else + { + w = [[x parentNode] leftNode]; + if (NODE_IS_RED(w)) + { + [w setBlack]; + [[x parentNode] setRed]; + [self rightRotateAroundNode:[x parentNode]]; + w = [[x parentNode] leftNode]; + } + if (NODE_IS_BLACK([w rightNode]) && NODE_IS_BLACK([w leftNode])) + { + [w setRed]; + x = [x parentNode]; + } + else + { + if (NODE_IS_BLACK([w leftNode])) + { + [[w rightNode] setBlack]; + [w setRed]; + [self leftRotateAroundNode:w]; + w = [[x parentNode] leftNode]; + } + if (NODE_IS_BLACK([x parentNode])) + [w setBlack]; + else + [w setRed]; + [[x parentNode] setBlack]; + [[w leftNode] setBlack]; + [self rightRotateAroundNode:[x parentNode]]; + x = _contents_root; + } + } + } + [x setBlack]; + return self; +} + +- (elt) removeElement: (elt)oldElement +{ + id x, y; + + if ([oldElement.id_u leftNode] == [self nilNode] + || [oldElement.id_u rightNode] == [self nilNode]) + y = oldElement.id_u; + else + y = [self successorOfElement:oldElement].id_u; + + if ([y leftNode] != [self nilNode]) + x = [y leftNode]; + else + x = [y rightNode]; + + [x setParentNode:[y parentNode]]; + + if ([y parentNode] == [self nilNode]) + _contents_root = x; + else + { + if (y == [[y parentNode] leftNode]) + [[y parentNode] setLeftNode:x]; + else + [[y parentNode] setRightNode:x]; + } + + if (y != oldElement.id_u) + { + /* put y in the place of oldElement.id_u */ + [y setParentNode:[oldElement.id_u parentNode]]; + [y setLeftNode:[oldElement.id_u leftNode]]; + [y setRightNode:[oldElement.id_u rightNode]]; + if (oldElement.id_u == [[oldElement.id_u parentNode] leftNode]) + [[oldElement.id_u parentNode] setLeftNode:y]; + else + [[oldElement.id_u parentNode] setRightNode:oldElement.id_u]; + [[oldElement.id_u leftNode] setParentNode:y]; + [[oldElement.id_u rightNode] setParentNode:y]; + } + + if (NODE_IS_BLACK(y)) + [self _RBTreeDeleteFixup:x]; + + [oldElement.id_u setRightNode:[self nilNode]]; + [oldElement.id_u setLeftNode:[self nilNode]]; + [oldElement.id_u setParentNode:[self nilNode]]; + _count--; + return oldElement; +} + +/* Override methods that could violate assumptions of RBTree structure. + Perhaps I shouldn't DISALLOW this, let users have the power to do + whatever they want. I mention this in the QUESTIONS section of the + TODO file. */ + +/*** +Or perhaps instead of calling INSERTION_ERROR we could fix up the RB +property of the tree. + +- insertElement: (elt)newElement before: (elt)oldElement +{ + INSERTION_ERROR(); + return self; +} + +- insertElement: (elt)newElement after: (elt)oldElement +{ + INSERTION_ERROR(); + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + INSERTION_ERROR(); + return self; +} + +- appendElement: (elt)newElement +{ + INSERTION_ERROR(); + return self; +} +****/ + +@end + diff --git a/Source/RBTreeEltNode.m b/Source/RBTreeEltNode.m new file mode 100644 index 000000000..7fe53b601 --- /dev/null +++ b/Source/RBTreeEltNode.m @@ -0,0 +1,37 @@ +/* Implementation for Objective-C RBTreeEltNode objects + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +@implementation RBTreeEltNode + ++ initialize +{ + if (self == [RBTreeEltNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +#include + +@end diff --git a/Source/RBTreeNode.m b/Source/RBTreeNode.m new file mode 100644 index 000000000..3358ba3c7 --- /dev/null +++ b/Source/RBTreeNode.m @@ -0,0 +1,86 @@ +/* Implementation for Objective-C RBTreeNode objects + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +@implementation RBTreeNode + ++ initialize +{ + if (self == [RBTreeNode class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- init +{ + [super init]; + _red = YES; + return self; +} + +- (void) encodeWithCoder: (Coder*)aCoder +{ + [super encodeWithCoder:aCoder]; + [aCoder encodeValueOfType:@encode(BOOL) at:&_red withName:"RBTreeNode isRed"]; +} + ++ newWithCoder: (Coder*)aCoder +{ + RBTreeNode *n = [super newWithCoder:aCoder]; + [aCoder decodeValueOfType:@encode(BOOL) at:&(n->_red) withName:NULL]; + return n; +} + +- write: (TypedStream*)aStream +{ + [super write:aStream]; + objc_write_type(aStream, @encode(BOOL), &_red); + return self; +} + +- read: (TypedStream*)aStream +{ + [super read:aStream]; + objc_read_type(aStream, @encode(BOOL), &_red); + return self; +} + +- (BOOL) isRed +{ + return _red; +} + +- setRed +{ + _red = YES; + return self; +} + +- setBlack +{ + _red = NO; + return self; +} + +@end diff --git a/Source/RNGAdditiveCongruential.m b/Source/RNGAdditiveCongruential.m new file mode 100644 index 000000000..3fdfa09ae --- /dev/null +++ b/Source/RNGAdditiveCongruential.m @@ -0,0 +1,112 @@ +/* Implementation additive congruential pseudo-random num generating + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +/* Additive Congruential Method, + from Robert Sedgewick, "Algorithms" */ + +/* The Chi^2 test results for this RNG is bad. + xxx Find the bug. */ + +@implementation RNGAdditiveCongruential + +- initWithTableSize: (int)s tapsAtOffsets: (int)t1 :(int)t2 +{ + [super init]; + table_size = s; + tap1 = t1; + tap2 = t2; + OBJC_MALLOC(table, long, table_size); + [self setRandomSeed:0]; + return self; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- free +{ + OBJC_FREE(table); + return [super free]; +} + +- init +{ + [self initWithTableSize:55 tapsAtOffsets:31 :55]; + return self; +} + +#define BITS_PER_CHAR 8 +#define HIGH_BYTE(X) ((X) / (1 << (sizeof(X)-1) * BITS_PER_CHAR)) + +- (long) nextRandom +{ + int i; + long result = 0; + + /* Grab only the high bytes---they are the most random */ + for (i = 0; i < sizeof(long); i++) + { + index = (index + 1) % table_size; + table[index] = (table[(index + table_size - tap1) % table_size] + + + table[(index + table_size - tap2) % table_size]); + result = (result << BITS_PER_CHAR) + HIGH_BYTE(table[index]); + } + return result; +} + +- (void) setRandomSeed: (long)s +{ + /* Fill the table with the linear congruential method, + from Robert Sedgewick, "Algorithms" */ + /* b must be x21, with x even, one less number of digits than ULONG_MAX */ + unsigned long b = ((ULONG_MAX / 1000) * 200) + 21; + unsigned char *byte_table = (unsigned char*) table; + int byte_table_size = table_size * sizeof(*table); + int i; + + for (i = 0; i < byte_table_size; i++) + { + s = s * b + 1; + byte_table[i] = HIGH_BYTE(s); + } + + /* Reset index to beginning */ + index = 0; + return; +} + +@end diff --git a/Source/RNGBerkeley.m b/Source/RNGBerkeley.m new file mode 100644 index 000000000..af08cadc0 --- /dev/null +++ b/Source/RNGBerkeley.m @@ -0,0 +1,442 @@ +/* Implementation of Berkeley random()-compatible generation for Objective-C + + Reworked by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Copyright (c) 1983 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * It was reworked for the GNU Objective-C Library by R. Andrew McCallum + */ + +#include +#include +#include +#include +#include +#include + +//#include + +/* Deal with bcopy: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define index strchr +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initiallized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroeth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroeth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least thi + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + +static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; +static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; + + + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroeth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +#if 0 /* moved to RNGBerkeley.h -am */ +static long int randtbl[DEG_3 + 1] = + { + TYPE_3, + -851904987, -43806228, -2029755270, 1390239686, -1912102820, + -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712, + -1714531963, 1800685987, -2015299881, 654595283, -1149023258, + -1470005550, -1143256056, -1325577603, -1568001885, 1275120390, + -607508183, -205999574, -1696891592, 1492211999, -1528267240, + -952028296, -189082757, 362343714, 1424981831, 2039449641, + }; +#endif /* moved to RNGBerkeley.h -am */ + +/* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + +#if 0 /* moved to RNGBerkeley.h -am */ +static long int *fptr = &randtbl[SEP_3 + 1]; +static long int *rptr = &randtbl[1]; +#endif /* moved to RNGBerkeley.h -am */ + + +/* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroeth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + +#if 0 /* moved to RNGBerkeley.h -am */ +static long int *state = &randtbl[1]; + +static int rand_type = TYPE_3; +static int rand_deg = DEG_3; +static int rand_sep = SEP_3; + +static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])]; +#endif /* moved to RNGBerkeley.h -am */ + + +@implementation RNGBerkeley + +- init +{ + static long int static_randtbl[DEG_3 + 1] = + { + TYPE_3, + -851904987, -43806228, -2029755270, 1390239686, -1912102820, + -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712, + -1714531963, 1800685987, -2015299881, 654595283, -1149023258, + -1470005550, -1143256056, -1325577603, -1568001885, 1275120390, + -607508183, -205999574, -1696891592, 1492211999, -1528267240, + -952028296, -189082757, 362343714, 1424981831, 2039449641, + }; + [super init]; + bcopy(static_randtbl, randtbl, sizeof(randtbl)); + fptr = &randtbl[SEP_3 + 1]; + rptr = &randtbl[1]; + state = &randtbl[1]; + rand_type = TYPE_3; + rand_deg = DEG_3; + rand_sep = SEP_3; + end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])]; + return self; +} + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +- (void) _srandom: (unsigned int)x +{ + state[0] = x; + if (rand_type != TYPE_0) + { + register long int i; + for (i = 1; i < rand_deg; ++i) + state[i] = (1103515145 * state[i - 1]) + 12345; + fptr = &state[rand_sep]; + rptr = &state[0]; + for (i = 0; i < 10 * rand_deg; ++i) + [self nextRandom]; /* (void) __random(); */ + } +} + +- (void) setRandomSeed: (long)aSeed +{ + [self _srandom:aSeed]; + return; +} + + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +- (void*) _initstateSeed: (unsigned int)seed + state: (void*)arg_state + size: (size_t)n +{ + void* ostate = (void*) &state[-1]; + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = (MAX_TYPES * (rptr - state)) + rand_type; + if (n < BREAK_1) + { + if (n < BREAK_0) + { + errno = EINVAL; + return NULL; + } + rand_type = TYPE_0; + rand_deg = DEG_0; + rand_sep = SEP_0; + } + else if (n < BREAK_2) + { + rand_type = TYPE_1; + rand_deg = DEG_1; + rand_sep = SEP_1; + } + else if (n < BREAK_3) + { + rand_type = TYPE_2; + rand_deg = DEG_2; + rand_sep = SEP_2; + } + else if (n < BREAK_4) + { + rand_type = TYPE_3; + rand_deg = DEG_3; + rand_sep = SEP_3; + } + else + { + rand_type = TYPE_4; + rand_deg = DEG_4; + rand_sep = SEP_4; + } + + state = &((long int *) arg_state)[1]; /* First location. */ + /* Must set END_PTR before srandom. */ + end_ptr = &state[rand_deg]; + [self _srandom:seed]; /*__srandom(seed); */ + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = (MAX_TYPES * (rptr - state)) + rand_type; + + return ostate; +} + + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroeth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +- (void*) _setstate: (void*)arg_state +{ + register long int *new_state = (long int *) arg_state; + register int type = new_state[0] % MAX_TYPES; + register int rear = new_state[0] / MAX_TYPES; + void* ostate = (void*) &state[-1]; + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = (MAX_TYPES * (rptr - state)) + rand_type; + + switch (type) + { + case TYPE_0: + case TYPE_1: + case TYPE_2: + case TYPE_3: + case TYPE_4: + rand_type = type; + rand_deg = degrees[type]; + rand_sep = seps[type]; + break; + default: + /* State info munged. */ + errno = EINVAL; + return NULL; + } + + state = &new_state[1]; + if (rand_type != TYPE_0) + { + rptr = &state[rear]; + fptr = &state[(rear + rand_sep) % rand_deg]; + } + /* Set end_ptr too. */ + end_ptr = &state[rand_deg]; + + return ostate; +} + + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all ther other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +- (long) nextRandom +{ + if (rand_type == TYPE_0) + { + state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX; + return state[0]; + } + else + { + long int i; + *fptr += *rptr; + /* Chucking least random bit. */ + i = (*fptr >> 1) & LONG_MAX; + ++fptr; + if (fptr >= end_ptr) + { + fptr = state; + ++rptr; + } + else + { + ++rptr; + if (rptr >= end_ptr) + rptr = state; + } + return i; + } +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +@end diff --git a/Source/Random.m b/Source/Random.m new file mode 100644 index 000000000..9f0f5f63e --- /dev/null +++ b/Source/Random.m @@ -0,0 +1,307 @@ +/* Implementation Objective-C object providing randoms in uniform distribution + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* TODO: + RNGBerkeley nextRandom returns only positive numbers + RNGAdditiveCongruential nextRandom returns positive and negative numbers +*/ + +#include +#include +#include +#include +#include +#include + +#define ABS(x) ((x) < 0 ? -x : x) + +typedef union { + float f; + unsigned long u; +} float_and_long_u; + +typedef union { + double d; + unsigned long u[2]; +} double_and_long_u; + +static float_and_long_u singleMantissa; +static double_and_long_u doubleMantissa; + +static id defaultRNG = nil; +@class RNGBerkeley; + +@implementation Random + ++ initialize +{ + if (self == [Random class]) + { + defaultRNG = [RNGBerkeley class]; + assert(sizeof(double) == 2 * sizeof(long)); + assert(sizeof(float) == sizeof(long)); + + /* Following taken from libg++ */ + + /* + 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. + */ + { + double_and_long_u t; + float_and_long_u 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; + 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 */ + t.d = x; + x += y; + y *= 0.5; + } while (x != t.d && x < 2.0); + + do { /*find largest fp-number < 2.0 */ + s.f = xx; + xx += yy; + yy *= 0.5; + } while (xx != s.f && 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.f = 1.0; + singleMantissa.u ^= s.u; + } + } + return self; +} + ++ setDefaultRandomGeneratorClass: (id )aRNG +{ + defaultRNG = aRNG; + return self; +} + ++ (id ) defaultRandomGeneratorClass +{ + return defaultRNG; +} + +/* For testing randomness of a random generator, + the closer to r the returned value is, the better the randomness. */ + ++ (float) chiSquareOfRandomGenerator: (id )aRNG + iterations: (int)n + range: (long)r +{ + long table[r]; + int i, j; + + for (i = 0; i < r; i++) + table[i] = 0; + for (i = 0; i < n; i++) + { + j = ABS([aRNG nextRandom]) % r; + table[j]++; + } + j = 0; + for (i = 0; i < r; i++) + j += table[i] * table[i]; + return ((((float)r * j) / n) - n); +} + +/* For testing randomness of a random generator, + the closer to 1.0 the returned value is, the better the randomness. */ + ++ (float) chiSquareOfRandomGenerator: (id )aRNG +{ + return [self chiSquareOfRandomGenerator:aRNG + iterations:1000 + range:100] / 100.0; +} + +- initWithRandomGenerator: (id )aRNG +{ + [super init]; + rng = aRNG; + return self; +} + +- init +{ + /* Without the (id) we get: + Random.m: In function `_i_Random__init': + Random.m:172: warning: method `alloc' not implemented by protocol. + This is a bug in gcc. + */ + return [self initWithRandomGenerator: + [[(id)[[self class] defaultRandomGeneratorClass] alloc] init]]; +} + +- setRandomSeedFromClock +{ + [self setRandomSeed:[Time secondClockValue]]; + return self; +} + +- setRandomSeed: (long)seed +{ + [rng setRandomSeed:seed]; + return self; +} + +- (long) randomInt +{ + return [rng nextRandom]; +} + +- (long) randomIntBetween: (long)lowBound and: (long)highBound +{ + return ([rng nextRandom] % (highBound - lowBound + 1) + lowBound); +} + +/* return between 0 and numSides-1 */ +- (long) randomDie: (long)numSides +{ + return ([rng nextRandom] % (numSides+1) - 1); +} + +- (BOOL) randomCoin +{ + return ([rng nextRandom] % 2); +} + +- (BOOL) randomCoinWithProbability: (double)p +{ + return (p >= [self randomDoubleProbability]); +} + +/* Returns 0.0 <= r < 1.0. Is this what people want? + I'd like it to return 1.0 also. */ +- (float) randomFloat +{ + union {long i; float f;} result; + result.f = 1.0; + result.i |= ([rng nextRandom] & singleMantissa.u); + result.f -= 1.0; + assert(result.f < 1.0 && result.f >= 0); + return result.f; +} + +- (float) randomFloatBetween: (float)lowBound and: (float)highBound +{ + return [self randomFloat] * (highBound - lowBound); +} + +- (float) randomFloatProbability +{ + return [self randomFloat]; +} + +/* Returns 0.0 <= r < 1.0. Is this what people want? + I'd like it to return 1.0 also. */ +- (double) randomDouble +{ + union {unsigned long u[2]; double d;} result; + + result.d = 1.0; + result.u[0] |= ([rng nextRandom] & doubleMantissa.u[0]); + result.u[1] |= ([rng nextRandom] & doubleMantissa.u[1]); + result.d -= 1.0; + assert(result.d < 1.0 && result.d >= 0); + return result.d; +} + +- (double) randomDoubleBetween: (double)lowBound and: (double)highBound +{ + return [self randomDouble] * (highBound - lowBound); +} + +- (double) randomDoubleProbability +{ + return [self randomDouble]; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- write: (TypedStream*)aStream +{ + [super write:aStream]; + // [rng read:aStream]; + [self notImplemented:_cmd]; + return self; +} + +- read: (TypedStream*)aStream +{ + [super read:aStream]; + // [rng read:aStream]; + [self notImplemented:_cmd]; + return self; +} + +@end diff --git a/Source/RetainingNotifier.m b/Source/RetainingNotifier.m new file mode 100644 index 000000000..d831735c8 --- /dev/null +++ b/Source/RetainingNotifier.m @@ -0,0 +1,145 @@ +/* Implementation of reference-counted invalidation notifer object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Reference Counted object with invalidation notification + This object is just temporary. Eventually, we should separate + reference counting functionality from notification functionality */ + +#include +#include +#include + +/* Use this for now, but GNU should switch to a GC pool + and separate notification. */ + +/* I really need to check the use of locks here */ + +@implementation RetainingNotifier + ++ initialize +{ + /* What goes here? */ + return self; +} + +- init +{ + retain_count = 0; + isValid = YES; + refGate = [[Lock alloc] init]; + notificationList = [[List alloc] init]; + return self; +} + +- (void) dealloc +{ + [refGate free]; + [notificationList free]; + [super free]; + return; +} + +- (oneway void) release +{ + [refGate lock]; + if (retain_count--) + { + [refGate unlock]; + return; + } + [refGate unlock]; + [self dealloc]; + return; +} + +- (id) retain +{ + [refGate lock]; + retain_count++; + [refGate unlock]; + return self; +} + +- free +{ + [self release]; + return nil; +} + +- (unsigned) retainCount +{ + return retain_count; +} + +- registerForInvalidationNotification: (id )anObject +{ + assert(refGate); + [refGate lock]; + [notificationList addObjectIfAbsent: anObject]; + [refGate unlock]; + return self; +} + +- unregisterForInvalidationNotification: (id )anObject +{ + assert(refGate); + [refGate lock]; + [notificationList removeObject: anObject]; + [refGate unlock]; + return self; +} + +- (BOOL) isValid +{ + return isValid; +} + +/* change name to -postInvalidation */ +- invalidate +{ + if (isValid == NO) + return nil; + [refGate lock]; + isValid = NO; + [notificationList makeObjectsPerform:@selector(senderIsInvalid:) with:self]; + [refGate unlock]; + return self; +} + + +- copy +{ + RetainingNotifier *newCopy = nil; + + if (isValid) + { + [refGate lock]; + newCopy = [[[self class] alloc] init]; + [newCopy->notificationList appendList:notificationList]; + newCopy->retain_count = retain_count; + [refGate unlock]; + } + return newCopy; +} + +@end diff --git a/Source/Set.m b/Source/Set.m new file mode 100644 index 000000000..06b5479e6 --- /dev/null +++ b/Source/Set.m @@ -0,0 +1,338 @@ +/* Implementation for Objective-C Set collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#define DEFAULT_SET_CAPACITY 32 + +@implementation Set + ++ initialize +{ + if (self == [Set class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// MANAGING CAPACITY; + +/* Eventually we will want to have better capacity management, + potentially keep default capacity as a class variable. */ + ++ (unsigned) defaultCapacity +{ + return DEFAULT_SET_CAPACITY; +} + +// INITIALIZING AND FREEING; + +/* This is the designated initializer of this class */ +- initWithType:(const char *)encoding + capacity: (unsigned)aCapacity +{ + [super initWithType:encoding]; + _contents_hash = + coll_hash_new(POWER_OF_TWO(aCapacity), + elt_get_hash_function(encoding), + elt_get_comparison_function(encoding)); + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) _encodeCollectionWithCoder: (Coder*) aCoder +{ + const char *enc = [self contentType]; + + [super _encodeCollectionWithCoder:aCoder]; + [aCoder encodeValueOfSimpleType:@encode(char*) + at:&enc + withName:"Set contents encoding"]; + [aCoder encodeValueOfSimpleType:@encode(unsigned) + at:&(_contents_hash->size) + withName:"Set contents capacity"]; + return; +} + ++ _newCollectionWithCoder: (Coder*) aCoder +{ + Set *newColl; + char *encoding; + unsigned size; + + newColl = [super _newCollectionWithCoder:aCoder]; + [aCoder decodeValueOfSimpleType:@encode(char*) + at:&encoding + withName:NULL]; + [aCoder decodeValueOfSimpleType:@encode(unsigned) + at:&size + withName:NULL]; + newColl->_contents_hash = + coll_hash_new(size, + elt_get_hash_function(encoding), + elt_get_comparison_function(encoding)); + return newColl; +} + +- _writeInit: (TypedStream*)aStream +{ + const char *encoding = [self contentType]; + + [super _writeInit:aStream]; + /* This implicitly archives the key's comparison and hash functions */ + objc_write_type(aStream, @encode(char*), &encoding); + objc_write_type(aStream, @encode(unsigned int), &(_contents_hash->size)); + return self; +} + +- _readInit: (TypedStream*)aStream +{ + char *encoding; + unsigned int size; + + [super _readInit:aStream]; + objc_read_type(aStream, @encode(char*), &encoding); + objc_read_type(aStream, @encode(unsigned int), &size); + _contents_hash = + coll_hash_new(size, + elt_get_hash_function(encoding), + elt_get_comparison_function(encoding)); + return self; +} + +/* Empty copy must empty an allocCopy'ed version of self */ +- emptyCopy +{ + Set *copy = [super emptyCopy]; + copy->_contents_hash = + coll_hash_new(_contents_hash->size, + _contents_hash->hash_func, + _contents_hash->compare_func); + return copy; +} + +/* Override designated initializer of superclass */ +- initWithType:(const char *)contentEncoding +{ + return [self initWithType:contentEncoding + capacity:[[self class] defaultCapacity]]; +} + +- initWithCapacity: (unsigned)aCapacity +{ + return [self initWithType:@encode(id) capacity:aCapacity]; +} + +- free +{ + coll_hash_delete(_contents_hash); + return [super free]; +} + +- freeObjects +{ + if (CONTAINS_OBJECTS) + { + [self makeObjectsPerform:@selector(free)]; + [self empty]; + } + else + [self empty]; + return self; +} + +// SET OPERATIONS; + +- intersectWithCollection: (id )aCollection +{ + [self removeContentsNotIn:aCollection]; + return self; +} + +- unionWithCollection: (id )aCollection +{ + [self addContentsOfIfAbsent:aCollection]; + return self; +} + +- differenceWithCollection: (id )aCollection +{ + [self removeContentsIn:aCollection]; + return self; +} + +- shallowCopyIntersectWithCollection: (id )aCollection +{ + id newColl = [self emptyCopyAs:[self species]]; + void doIt(elt e) + { + if ([aCollection includesElement:e]) + [newColl addElement:e]; + } + [self withElementsCall:doIt]; + return newColl; +} + +- shallowCopyUnionWithCollection: (id )aCollection +{ + id newColl = [self shallowCopy]; + + [newColl addContentsOf:aCollection]; + return newColl; +} + +- shallowCopyDifferenceWithCollection: (id )aCollection +{ + id newColl = [self emptyCopyAs:[self species]]; + void doIt(elt e) + { + if (![aCollection includesElement:e]) + [newColl addElement:e]; + } + [self withElementsCall:doIt]; + return newColl; +} + + +// ADDING; + +- addElement: (elt)anElement +{ + if (coll_hash_value_for_key(_contents_hash, anElement).void_ptr_u == 0) + coll_hash_add(&_contents_hash, anElement, 1); + return self; +} + + +// REMOVING AND REPLACING; + +- (elt) removeElement: (elt)oldElement ifAbsent: (elt(*)(arglist_t))excFunc +{ + if (coll_hash_value_for_key(_contents_hash, oldElement).void_ptr_u == 0) + coll_hash_remove(_contents_hash, oldElement); + else + RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc); + return oldElement; +} + +/* This must work without sending any messages to content objects */ +- empty +{ + coll_hash_empty(_contents_hash); + return self; +} + +- uniqueContents +{ + return self; +} + + +// TESTING; + +- (int(*)(elt,elt)) comparisonFunction +{ + return _contents_hash->compare_func; +} + +- (const char *) contentType +{ + return elt_get_encoding(_contents_hash->compare_func); +} + +- (BOOL) includesElement: (elt)anElement +{ + if (coll_hash_value_for_key(_contents_hash, anElement).void_ptr_u != 0) + return YES; + else + return NO; +} + +- (unsigned) count +{ + return _contents_hash->used; +} + +- (unsigned) occurrencesOfElement: (elt)anElement +{ + if ([self includesElement:anElement]) + return 1; + else + return 0; +} + + +// ENUMERATING; + +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState +{ + coll_node_ptr node = coll_hash_next(_contents_hash, enumState); + if (node) + { + *anElementPtr = node->key; + return YES; + } + return NO; +} + +- (void*) newEnumState +{ + return (void*)0; +} + +- freeEnumState: (void**)enumState +{ + if (*enumState) + OBJC_FREE(*enumState); + return self; +} + +- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag +{ + void *state = 0; + coll_node_ptr node; + + while (*flag && (node = coll_hash_next(_contents_hash, &state))) + { + (*aFunc)(node->key); + } + return self; +} + +- withElementsCall: (void(*)(elt))aFunc +{ + void *state = 0; + coll_node_ptr node = 0; + + while ((node = coll_hash_next(_contents_hash, &state))) + { + (*aFunc)(node->key); + } + return self; +} + + +@end + diff --git a/Source/SocketPort.m b/Source/SocketPort.m new file mode 100644 index 000000000..e755514d0 --- /dev/null +++ b/Source/SocketPort.m @@ -0,0 +1,430 @@ +/* Implementation of socket-based port object for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Deal with bcopy: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define index strchr +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + +/* Make this a hashtable? */ +static List* socketPortList; +static Lock* socketPortListGate; + +static BOOL socket_port_debug = NO; + +/* xxx This function is just temporary. + Eventually we should write a real name server for sockets */ +static unsigned int +name_to_port_number (const char *name) +{ + unsigned int ret = 0; + unsigned int ctr = 0; + + while (*name) + { + ret ^= *name++ << ctr; + ctr = (ctr + 1) % sizeof (void *); + } + return ret % (65535 - IPPORT_USERRESERVED - 1); +} + +@implementation SocketPort + ++ initialize +{ + if ([self class] == [SocketPort class]) + { + socketPortList = [[List alloc] init]; + socketPortListGate = [Lock new]; + } + return self; +} + ++ setDebug: (BOOL)f +{ + socket_port_debug = f; + return self; +} + ++ newPortFromRegisterWithName: (const char *)name onHost: (const char *)h +{ + id p; + int n; + +#if SOCKETPORT_NUMBER_NAMES_ONLY + if ((n = atoi(name)) == 0) + [self error:"Name (%s) is not a number", name]; +#else + n = name_to_port_number(name); +#endif + p = [SocketPort newRemoteWithNumber:n onHost:h]; + return p; +} + ++ newRegisteredPortWithName: (const char *)name +{ + int n; + +#if SOCKET_NUMBER_NAMES_ONLY + if ((n = atoi(name)) == 0) + return nil; +#else + n = name_to_port_number(name); +#endif + return [SocketPort newLocalWithNumber:n]; +} + ++ newPort +{ + return [self newLocal]; +} + +/* xxx Change this to consider INADDR_ANY and the localhost address + to be equal. */ +#define SOCKPORT_EQUAL(s1,s2) \ +(s1.sin_port == s2.sin_port && \ +s1.sin_addr.s_addr == s2.sin_addr.s_addr) +/* Assume that sin_family is equal */ + +/* (!memcmp(&s1, &s2, sizeof(sockport_t))) + didn't work because sin_zero's differ. Does this matter? */ + ++ newForSockPort: (sockport_t)s close: (BOOL)f +{ + SocketPort* sp; + int i, count; + sockport_t a; + + [socketPortListGate lock]; + + /* See if there is already one created */ + count = [socketPortList count]; + for (i = 0; i < count; i++) + { + sp = [socketPortList objectAt:i]; + a = [sp sockPort]; + if (SOCKPORT_EQUAL(a, s)) + { + [socketPortListGate unlock]; + return sp; + } + } + + /* No, create a new one */ + if (s.sin_family != AF_INET) + [self error:"we don't do non INET socket addresses"]; + sp = [[self alloc] init]; + sp->sockPort = s; + sp->close_on_dealloc = f; + /* Before we allowed (s.sin_addr.s_addr == htonl(INADDR_LOOPBACK) also, + but then we couldn't have both server and client on the same + machine. It would think that the client's out port to the server's + in port should be bind()'ed, but the server already did that. */ + if (s.sin_addr.s_addr == INADDR_ANY) + { + /* it's local */ + if ((sp->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("creating socket"); + [self error:"creating socket"]; + } + i = sizeof(sockport_t); + if (bind(sp->sock, (struct sockaddr*)&sp->sockPort, i)) + { + perror("bind"); + [self error:"binding socket"]; + } + if (getsockname(sp->sock, (struct sockaddr*)&sp->sockPort, &i)) + { + perror("getsockname"); + [self error:"getsockname socket"]; + } + if (socket_port_debug) + fprintf(stderr, "new socket(), fd=%d\n", sp->sock); + } + if (socket_port_debug) + fprintf(stderr, "created new SocketPort 0x%x, number %d\n", + (unsigned)sp, [sp socketPortNumber]); + [socketPortList addObject:sp]; + [socketPortListGate unlock]; + + return sp; +} + +- (void) dealloc +{ + if (sock && close_on_dealloc) + close(sock); + [super dealloc]; + return; +} + ++ newForSockPort: (sockport_t)s +{ + return [self newForSockPort:s close:YES]; +} + ++ newLocalWithNumber: (int)n +{ + sockport_t s; + SocketPort* sp; + + /* xxx clean this up */ + if (n > 65535 - IPPORT_USERRESERVED - 1) + [self error:"port number too high"]; + n += IPPORT_USERRESERVED + 1; + + /* xxx bzero(&s, sizeof(s)) necessary here? */ + s.sin_family = AF_INET; + s.sin_addr.s_addr = INADDR_ANY; + s.sin_port = htons(n); + sp = [self newForSockPort:s close:YES]; + return sp; +} + ++ newLocal +{ + id sp; + sockport_t a; + + a.sin_family = AF_INET; + a.sin_addr.s_addr = INADDR_ANY; + a.sin_port = 0; + sp = [self newForSockPort:a]; + return sp; +} + ++ newRemoteWithNumber: (int)n onHost: (const char*)h +{ + struct sockaddr_in remote_addr; + struct hostent *hp; + + /* xxx clean this up */ + if (n > 65535 - IPPORT_USERRESERVED - 1) + [self error:"port number too high"]; + n += IPPORT_USERRESERVED + 1; + + if (!h || !(*h)) + h = "localhost"; + + hp = gethostbyname((char*)h); + if (hp == 0) + [self error:"unknown host: \"%s\"", h]; + bcopy(hp->h_addr, &remote_addr.sin_addr, hp->h_length); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(n); + return [self newForSockPort:remote_addr]; +} + + +/* This currently ignores the timeout parameter */ + +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*)remote + timeout: (int) milliseconds; +{ + int r; + sockport_t a; + + if (![remote isKindOf:[SocketPort class]]) + [self error:"Trying to send to a non-SocketPort"]; + a = [(SocketPort*)remote sockPort]; + if (socket_port_debug) + fprintf(stderr, "sending to %d\n", [(SocketPort*)remote socketPortNumber]); + if ((r = sendto([self socket], (char*)b, l, 0, (struct sockaddr *)&a, + sizeof(sockport_t))) + < 0) + { + perror("sendto"); + [self error:"sendto"]; + } + return r; +} + +/* Returns -1 on timeout. + Pass -1 for milliseconds to ignore timeout parameter and block indefinitely. +*/ + +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote + timeout: (int) milliseconds; +{ + int r; + struct sockaddr_in remote_addr; + int remote_len; + int local_sock; + + if (socket_port_debug) + fprintf(stderr, "receiving from %d\n", [self socketPortNumber]); + + local_sock = [self socket]; + + if (milliseconds >= 0) + { + struct timeval timeout; + fd_set ready; + + timeout.tv_sec = milliseconds / 1000; + timeout.tv_usec = (milliseconds % 1000) * 1000; + FD_ZERO(&ready); + FD_SET(local_sock, &ready); + if ((r = select(local_sock + 1, &ready, 0, 0, &timeout)) < 0) + { + perror("select"); + [self error:"select"]; + } + if (r == 0) /* timeout */ + return -1; + if (!FD_ISSET(local_sock, &ready)) + [self error:"select lied"]; + } + + remote_len = sizeof(sockport_t); + if ((r = recvfrom(local_sock, b, l, 0, (struct sockaddr*)&remote_addr, + &remote_len)) + < 0) + { + perror("recvfrom"); + [self error:"recvfrom"]; + } + if (remote_len != sizeof(sockport_t)) + [self error:"remote address size mismatch"]; + *remote = [[self class] newForSockPort:remote_addr close:NO]; + return r; +} + +- (sockport_t) sockPort +{ + return sockPort; +} + +- classForConnectedCoder: aRmc +{ + /* Make sure that Connection's always send us bycopy, + i.e. as our own class, not a Proxy class. */ + return [self class]; +} + +- (void) encodeWithCoder: aCoder +{ + [aCoder encodeValueOfType:@encode(typeof(sockPort.sin_port)) + at:&sockPort.sin_port + withName:"socket number"]; + if (![self isSoft]) + { + struct hostent *hp; + sockport_t sp; + + /* xxx this could be cleaned up */ + hp = gethostbyname("localhost"); + if (hp == 0) + [self error:"gethostbyname(): can't get host info"]; + bcopy(hp->h_addr, &sp.sin_addr, hp->h_length); + [aCoder encodeValueOfType:@encode(typeof(sp.sin_addr.s_addr)) + at:&sp.sin_addr.s_addr + withName:"inet address"]; + } + else + { + [aCoder encodeValueOfType:@encode(typeof(sockPort.sin_addr.s_addr)) + at:&sockPort.sin_addr.s_addr + withName:"inet address"]; + } +} + ++ newWithCoder: aCoder +{ + sockport_t sp; + + sp.sin_family = AF_INET; + [aCoder decodeValueOfType:@encode(typeof(sp.sin_port)) + at:&sp.sin_port + withName:NULL]; + [aCoder decodeValueOfType:@encode(typeof(sp.sin_addr.s_addr)) + at:&sp.sin_addr.s_addr + withName:NULL]; + return [SocketPort newForSockPort:sp]; +} + +- (int) socket +{ + return sock; +} + +- (BOOL) isSoft +{ + if (sock) + return NO; + else + return YES; +} + +- (int) socketPortNumber +{ + return (int) ntohs(sockPort.sin_port); +} + +- (unsigned) hash +{ + unsigned h = [self socketPortNumber] + sockPort.sin_addr.s_addr; + return h; +} + +- (BOOL) isEqual: anotherPort +{ + sockport_t s = [anotherPort sockPort]; + if (SOCKPORT_EQUAL(s, sockPort)) + { + /* xxx Is this really a problem? */ + if (self != anotherPort) + [self error: + "Another SocketPort object with the same underlying address!"]; + return YES; + } + return NO; +} + +@end diff --git a/Source/SplayTree.m b/Source/SplayTree.m new file mode 100644 index 000000000..8e32c7774 --- /dev/null +++ b/Source/SplayTree.m @@ -0,0 +1,133 @@ +/* Implementation for Objective-C SplayTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +@implementation SplayTree + ++ initialize +{ + if (self == [SplayTree class]) + [self setVersion:0]; /* beta release */ + return self; +} + +/* Make this a function ? */ +- _doSplayOperationOnNode: aNode +{ + id parent = [aNode parentNode]; + id parentRightChild = + ((parent == [self nilNode]) ? [self nilNode] : [parent rightNode]); + + if (aNode == _contents_root || aNode == [self nilNode]) + { + return self; + } + else if (aNode == parentRightChild) + { + if (parent == _contents_root) + { + [self leftRotateAroundNode:parent]; + } + else if (NODE_IS_RIGHTCHILD(parent)) + { + [self leftRotateAroundNode:[parent parentNode]]; + [self leftRotateAroundNode:parent]; + } + else + /* NODE_IS_LEFTCHILD(parent) */ + { + [self leftRotateAroundNode:parent]; + [self rightRotateAroundNode:[aNode parentNode]]; + } + } + else + /* aNode == parentLeftChild */ + { + if (parent == _contents_root) + { + [self rightRotateAroundNode:parent]; + } + else if (NODE_IS_LEFTCHILD(parent)) + { + [self rightRotateAroundNode:[parent parentNode]]; + [self rightRotateAroundNode:parent]; + } + else + /* NODE_IS_RIGHTCHILD(parent) */ + { + [self rightRotateAroundNode:parent]; + [self leftRotateAroundNode:[aNode parentNode]]; + } + } + return self; +} + +- splayNode: aNode +{ + while (aNode != _contents_root) + [self _doSplayOperationOnNode:aNode]; + return self; +} + +/* We could make this a little more efficient by doing the splay as + we search down the tree for the correct insertion point. */ +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc +{ + [super sortAddElement:newElement byCalling:aFunc]; + [self splayNode:newElement.id_u]; + return self; +} + +- insertElement: (elt)newElement before: (elt)oldElement +{ + [super insertElement:newElement before:oldElement]; + // ?? [self splayNode:newElement.id_u]; + return self; +} + +- insertElement: (elt)newElement after: (elt)oldElement +{ + [super insertElement:newElement after:oldElement]; + // ?? [self splayNode:newElement.id_u]; + return self; +} + +- insertElement: (elt)newElement atIndex: (unsigned)index +{ + [super insertElement:newElement atIndex:index]; + // ?? [self splayNode:newElement.id_u]; + return self; +} + +- (elt) removeElement: (elt)anElement +{ + id parent = [anElement.id_u parentNode]; + [super removeElement:anElement]; + if (parent && parent != [self nilNode]) + [self splayNode:parent]; + return anElement; +} + +@end diff --git a/Source/Stack.m b/Source/Stack.m new file mode 100644 index 000000000..985bec889 --- /dev/null +++ b/Source/Stack.m @@ -0,0 +1,91 @@ +/* Implementation for Objective-C Stack object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +@implementation Stack + ++ initialize +{ + if (self == [Stack class]) + [self setVersion:0]; /* beta release */ + return self; +} + +- pushElement: (elt)anElement +{ + [self appendElement:anElement]; + return self; +} + +/* Overriding */ +- addElement: (elt)anElement +{ + [self pushElement:anElement]; + return self; +} + +- (elt) popElement +{ + return [self removeLastElement]; +} + +- (elt) topElement +{ + return [self lastElement]; +} + +/* Yipes. What copying semantics do we want here? */ +- duplicateTop +{ + [self pushElement:[self topElement]]; + return self; +} + +- exchangeTop +{ + if (_count <= 1) + return nil; + [self swapAtIndeces:_count-1 :_count-2]; + return self; +} + +// OBJECT-COMPATIBLE MESSAGE NAMES; + +- pushObject: anObject +{ + return [self pushElement:anObject]; +} + +- popObject +{ + return [self popElement].id_u; +} + +- topObject +{ + return [self topElement].id_u; +} + +@end diff --git a/Source/StdioStream.m b/Source/StdioStream.m new file mode 100644 index 000000000..37d8040b6 --- /dev/null +++ b/Source/StdioStream.m @@ -0,0 +1,220 @@ +/* Implementation of GNU Objective C stdio stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +extern int +objects_vscanf (void *stream, + int (*inchar_func)(void*), + void (*unchar_func)(void*,int), + const char *format, va_list argptr); + +@implementation StdioStream + ++ standardIn +{ + static id stdinStream = nil; + + if (!stdinStream) + stdinStream = [[self alloc] initWithFilePointer:stdin fmode:"r"]; + return stdinStream; +} + ++ standardOut +{ + static id stdoutStream = nil; + + if (!stdoutStream) + stdoutStream = [[self alloc] initWithFilePointer:stdout fmode:"w"]; + return stdoutStream; +} + ++ standardError +{ + static id stderrStream = nil; + + if (!stderrStream) + stderrStream = [[self alloc] initWithFilePointer:stderr fmode:"w"]; + return stderrStream; +} + +- initWithFilePointer: (FILE*)afp fmode: (const char *)mo +{ + int m; +#if 0 + /* xxx Is this portable? I don't think so. + How do I find out if a FILE* is open for reading/writing? */ + if (afp->_flag & _IOREAD) + m = STREAM_READONLY; + else if (afp->_flag & _IOWRT) + m = STREAM_WRITEONLY; + else + m = STREAM_READWRITE; +#else + if (!strcmp(mo, "rw")) + m = STREAM_READWRITE; + else if (*mo == 'r') + m = STREAM_READONLY; + else if (*mo == 'w') + m = STREAM_WRITEONLY; +#endif + [super initWithMode:m]; + fp = afp; + return self; +} + +- initWithFilename: (const char *)name fmode: (const char *)m +{ + FILE *afp = fopen(name, (char*)m); + return [self initWithFilePointer:afp fmode:m]; +} + +- initWithFileDescriptor: (int)fd fmode: (const char *)m +{ + FILE *afp = fdopen(fd, (char*)m); + return [self initWithFilePointer:afp fmode:m]; +} + +- initWithPipeTo: (const char *)systemCommand +{ + return [self initWithFilePointer: + popen(systemCommand, "w") + fmode:"w"]; +} + +- initWithPipeFrom: (const char *)systemCommand +{ + return [self initWithFilePointer: + popen(systemCommand, "r") + fmode:"r"]; +} + +- init +{ + return [self initWithFilePointer:stdout fmode:"w"]; +} + +- (int) writeBytes: (const void*)b length: (int)len +{ + return fwrite(b, 1, len, fp); +} + +- (int) readBytes: (void*)b length: (int)len +{ + return fread(b, 1, len, fp); +} + +- (int) writeFormat: (const char *)format, ... +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = vfprintf(fp, format, ap); + va_end(ap); + return ret; +} + +static int +stdio_inchar_func(void *s) +{ + return getc((FILE*)s); +} +static void +stdio_unchar_func(void *s, int c) +{ + ungetc(c, (FILE*)s); +} + +- (int) readFormat: (const char *)format, ... +{ + int ret; + va_list ap; +/* Wow. Why does putting in these nested functions crash the + va_arg stuff in vscanf? */ +#if 0 + int inchar_func() + { + return getc(fp); + } + void unchar_func(int c) + { + ungetc(c, fp); + } +#endif + + va_start(ap, format); + ret = objects_vscanf(fp, stdio_inchar_func, stdio_unchar_func, format, ap); + va_end(ap); + return ret; +} + +- (void) flushStream +{ + fflush(fp); +} + +- (void) rewindStream +{ + rewind(fp); +} + +- (void) setStreamPosition: (unsigned)i +{ + fseek(fp, i, 0); +} + +- (unsigned) streamPosition +{ + return ftell(fp); +} + +- (BOOL) streamEof +{ + if (feof(fp)) + return YES; + else + return NO; +} + +- free +{ + fclose(fp); + return [super free]; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +@end diff --git a/Source/Storage.m b/Source/Storage.m new file mode 100644 index 000000000..83a517c87 --- /dev/null +++ b/Source/Storage.m @@ -0,0 +1,301 @@ +/* Implementation of Objective C NeXT-compatible Storage object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +/* memcpy() and memcmp() are gcc builtin's */ + +/* Deal with bzero: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define index strchr +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + + +#define GNU_STORAGE_NTH(x,N) \ + ({ GNUStorageId* __s=(GNUStorageId*)(x); \ + (void*)(((char*)__s->dataPtr)+(__s->elementSize*(N))); }) +#define STORAGE_NTH(N) GNU_STORAGE_NTH (self, N) + +typedef struct { + @defs(Storage) +} GNUStorageId; + +@implementation Storage + ++ initialize +{ + if (self == [Storage class]) + [self setVersion:0]; /* beta release */ + return self; +} + +// INITIALIZING, FREEING; + +- initCount: (unsigned)numSlots + elementSize: (unsigned)sizeInBytes + description: (const char*)elemDesc; +{ + [super init]; + numElements = numSlots; + maxElements = (numSlots > 0) ? numSlots : 1; + elementSize = sizeInBytes; + description = elemDesc; + dataPtr = (void*) (*objc_malloc)(maxElements * elementSize); + bzero(dataPtr, numElements * elementSize); + return self; +} + +- init +{ + return [self initCount:1 + elementSize:sizeof(id) + description:@encode(id)]; +} + + +- free +{ + if (dataPtr) + free(dataPtr); + return [super free]; +} + +- (const char*) description +{ + return description; +} + + +// COPYING; + +- shallowCopy +{ + Storage *c = [super shallowCopy]; + c->dataPtr = (void*) (*objc_malloc)(maxElements * elementSize); + memcpy(c->dataPtr, dataPtr, numElements * elementSize); + return c; +} + +// COMPARING TWO STORAGES; + +- (BOOL)isEqual: anObject +{ + if ([anObject isKindOf: [Storage class]] + && [anObject count] == [self count] + && !memcmp(((GNUStorageId*)anObject)->dataPtr, + dataPtr, numElements*elementSize)) + return YES; + else + return NO; +} + +// MANAGING THE STORAGE CAPACITY; + +static inline void _makeRoomForAnotherIfNecessary(Storage *self) +{ + if (self->numElements == self->maxElements) + { + assert(self->maxElements); + self->maxElements *= 2; + self->dataPtr = (void*) + (*objc_realloc)(self->dataPtr, self->maxElements*self->elementSize); + } +} + +static inline void _shrinkIfDesired(Storage *self) +{ + if (self->numElements < (self->maxElements / 2)) + { + self->maxElements /= 2; + self->dataPtr = (void *) + (*objc_realloc)(self->dataPtr, self->maxElements*self->elementSize); + } +} + +- setAvailableCapacity:(unsigned)numSlots +{ + if (numSlots > numElements) + { + maxElements = numSlots; + dataPtr = (void*) (*objc_realloc)(dataPtr, maxElements * elementSize); + } + return self; +} + +- setNumSlots:(unsigned)numSlots +{ + if (numSlots > numElements) + { + maxElements = numSlots; + dataPtr = (void*) (*objc_realloc)(dataPtr, maxElements * elementSize); + bzero(STORAGE_NTH(numElements), (maxElements-numElements)*elementSize); + } + else if (numSlots < numElements) + { + numElements = numSlots; + _shrinkIfDesired (self); + } + return self; +} + +/* Manipulating objects by index */ + +#define CHECK_INDEX(IND) if (IND >= numElements) return 0 + +- (unsigned) count +{ + return numElements; +} + +- (void*) elementAt: (unsigned)index +{ + CHECK_INDEX(index); + return STORAGE_NTH (index); +} + +- addElement: (void*)anElement +{ + _makeRoomForAnotherIfNecessary(self); + memcpy(STORAGE_NTH(numElements), anElement, elementSize); + numElements++; + return self; +} + +- insertElement: (void*)anElement at: (unsigned)index +{ + int i; + + CHECK_INDEX(index); + _makeRoomForAnotherIfNecessary(self); +#ifndef STABLE_MEMCPY + for (i = numElements; i >= index; i--) + memcpy (STORAGE_NTH(i+1), STORAGE_NTH(i), elementSize); +#else + memcpy (STORAGE_NTH (index+1), + STORAGE_NTH (index), + elementSize*(numElements-index)); +#endif + memcpy(STORAGE_NTH(i), anElement, elementSize); + return self; +} + +- removeElementAt: (unsigned)index +{ + int i; + + CHECK_INDEX(index); + numElements--; +#ifndef STABLE_MEMCPY + for (i = index; i < numElements; i++) + memcpy(STORAGE_NTH(i), + STORAGE_NTH(i+1), + elementSize); +#else + memcpy (STORAGE_NTH (index), + STORAGE_NTH (index+1), + elementSize*(numElements-index-1)); +#endif + _shrinkIfDesired(self); + return self; +} + +- removeLastElement +{ + if (numElements) + { + numElements--; + _shrinkIfDesired(self); + } + return self; +} + +- replaceElementAt:(unsigned)index with:(void*)newElement +{ + CHECK_INDEX(index); + memcpy(STORAGE_NTH(index), newElement, elementSize); + return self; +} + +/* Emptying the Storage */ + +- empty +{ + numElements = 0; + maxElements = 1; + dataPtr = (void*) (*objc_realloc)(dataPtr, maxElements * elementSize); + return self; +} + +/* Archiving */ + +- write: (TypedStream*)aStream +{ + int i; + + [super write:aStream]; + objc_write_types(aStream, "III*", + &numElements, &maxElements, &elementSize, &description); + for (i = 0; i < numElements; i++) + objc_write_type(aStream, description, STORAGE_NTH(i)); + return self; +} + +- read: (TypedStream*)aStream +{ + int i; + + [super read:aStream]; + objc_read_types(aStream, "III*", + &numElements, &maxElements, &elementSize, &description); + dataPtr = (void*) (*objc_malloc)(maxElements * elementSize); + for (i = 0; i < numElements; i++) + objc_read_type(aStream, description, STORAGE_NTH(i)); + return self; +} + ++ new +{ + return [[self alloc] init]; +} + ++ newCount:(unsigned)count elementSize:(unsigned)sizeInBytes + description:(const char *)descriptor +{ + return [[self alloc] initCount:count elementSize:sizeInBytes + description:descriptor]; +} + +@end diff --git a/Source/Stream.m b/Source/Stream.m new file mode 100644 index 000000000..3c7acd6d5 --- /dev/null +++ b/Source/Stream.m @@ -0,0 +1,152 @@ +/* Implementation of GNU Objective C byte stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +@implementation Stream + +- initWithMode: (int)m +{ + [super init]; + mode = m; + return self; +} + +- init +{ + return [self initWithMode:STREAM_READWRITE]; +} + +#if 0 +- (void) close +{ + /* nothing needed */ +} +#endif + +- (int) writeByte: (unsigned char)b +{ + return [self writeBytes:&b length:1]; +} + +- (int) readByte: (unsigned char*)b +{ + return [self readBytes:b length:1]; +} + +- (int) writeBytes: (const void*)b length: (int)l +{ + [self notImplemented:_cmd]; + return 0; +} + +- (int) readBytes: (void*)b length: (int)l +{ + [self notImplemented:_cmd]; + return 0; +} + +- (int) writeFormat: (const char *)format, ... +{ + [self notImplemented:_cmd]; + return 0; +} + +- (int) readFormat: (const char *)format, ... +{ + [self notImplemented:_cmd]; + return 0; +} + +- (void) writeLine: (const char *)l +{ + [self writeFormat:"%s\n", l]; +} + +/* This malloc's the buffer pointed to by the return value */ +- (char *) readLine +{ + char *l; + [self readFormat:"%a[^\n]\n", &l]; + return l; +} + +- (void) rewindStream +{ + [self setStreamPosition:0]; +} + +- (void) flushStream +{ + [self notImplemented:_cmd]; +} + +- (void) setStreamPosition: (unsigned)i +{ + [self notImplemented:_cmd]; +} + +- (unsigned) streamPosition +{ + [self notImplemented:_cmd]; + return 0; +} + +- (BOOL) streamEof +{ + [self notImplemented:_cmd]; + return YES; +} + +- (int) streamMode +{ + return mode; +} + +#if 0 /* Put this into a StreamStream class? */ +- initWithStream: (Stream *)s mode: (int)m +{ + if (m == STREAM_READONLY && [s streamMode] == STREAM_READONLY + || m == STREAM_WRITEONLY && [s streamMode] == STREAM_WRITEONLY) + [self error:"Streams read/write modes conflict"]; + [super initWithMode:m]; + otherStream = s; + return self; +} +#endif + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +@end diff --git a/Source/TextCoder.m b/Source/TextCoder.m new file mode 100644 index 000000000..d4e2ed923 --- /dev/null +++ b/Source/TextCoder.m @@ -0,0 +1,285 @@ +/* Implementation of GNU Objective-C text coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#define CONCRETE_FORMAT_VERSION 0 + +static BOOL debug_textcoder = NO; + +@implementation TextCoder + ++ (int) coderConcreteFormatVersion +{ + return CONCRETE_FORMAT_VERSION; +} + +/* Careful, this shouldn't contain newlines */ ++ (const char *) coderSignature +{ + return "GNU Objective C Class Library TextCoder"; +} + +- doInitOnStream: (Stream *)s isDecoding: (BOOL)f +{ + [super doInitOnStream:s isDecoding:f]; + indentation = 0; + return self; +} + +#define XSTR(s) STR(s) +#define STR(s) #s + +#define ENCODER_FORMAT(TYPE, CONVERSION) \ +"%*s<%s> (" XSTR(TYPE) ") = %" XSTR(CONVERSION) "\n" + +- (void) encodeValueOfSimpleType: (const char*)type + at: (const void*)d + withName: (const char *)name +{ + if (!name) + name = ""; + switch (*type) + { + case _C_LNG: + [stream writeFormat:"%*s<%s> (long) = %ld\n", + indentation, "", name, *(long*)d]; + break; + case _C_ULNG: + [stream writeFormat:"%*s<%s> (unsigned long) = %lu\n", + indentation, "", name, *(unsigned long*)d]; + break; + case _C_INT: + [stream writeFormat:"%*s<%s> (int) = %d\n", + indentation, "", name, *(int*)d]; + break; + case _C_UINT: + [stream writeFormat:"%*s<%s> (unsigned int) = %u\n", + indentation, "", name, *(unsigned int*)d]; + break; + case _C_SHT: + [stream writeFormat:"%*s<%s> (short) = %d\n", + indentation, "", name, (int)*(short*)d]; + break; + case _C_USHT: + [stream writeFormat:"%*s<%s> (unsigned short) = %u\n", + indentation, "", name, (unsigned)*(unsigned short*)d]; + break; + case _C_CHR: + [stream writeFormat:"%*s<%s> (char) = %c (0x%x)\n", + indentation, "", name, *(char*)d, (unsigned)*(char*)d]; + break; + case _C_UCHR: + [stream writeFormat:"%*s<%s> (unsigned char) = 0x%x\n", + indentation, "", name, (unsigned)*(unsigned char*)d]; + break; + case _C_FLT: + [stream writeFormat:"%*s<%s> (float) = %f\n", + indentation, "", name, *(float*)d]; + break; + case _C_DBL: + [stream writeFormat:"%*s<%s> (double) = %f\n", + indentation, "", name, *(double*)d]; + break; + case _C_CHARPTR: + [stream writeFormat:"%*s<%s> (char*) = \"%s\"\n", + indentation, "", name, *(char**)d]; + break; + default: + [self error:"type %s not yet implemented", type]; + } +} + +#define DECODER_FORMAT(TYPE, CONVERSION) \ +" <%a[^>]> (" XSTR(TYPE) ") = %" XSTR(CONVERSION) " \n" + +#define DECODE_ERROR(TYPE) [self error:"bad format decoding " XSTR(TYPE)] + +#define DECODE_DEBUG(TYPE, CONVERSION) \ +if (debug_textcoder) \ + [[StdioStream standardError] writeFormat:"got <%s> (%s) %" \ + XSTR(CONVERSION) "\n", \ + tmpname, \ + XSTR(TYPE), *(TYPE*)d]; + + +- (void) decodeValueOfSimpleType: (const char*)type + at: (void*)d + withName: (const char **)name +{ + char *tmpname; + + switch (*type) + { + case _C_LNG: + if ([stream readFormat:DECODER_FORMAT(long,l), + &tmpname, (long*)d] != 2) + DECODE_ERROR(long); + DECODE_DEBUG(long, l); + break; + case _C_ULNG: + if ([stream readFormat:DECODER_FORMAT(unsigned long, lu), + &tmpname, (unsigned long*)d] != 2) + DECODE_ERROR(unsigned long); + DECODE_DEBUG(unsigned long, lu); + break; + case _C_INT: + if ([stream readFormat:DECODER_FORMAT(int, d), + &tmpname, (int*)d] != 2) + DECODE_ERROR(int); + DECODE_DEBUG(int, d); + break; + case _C_UINT: + if ([stream readFormat:DECODER_FORMAT(unsigned int,u), + &tmpname, (unsigned int*)d] != 2) + DECODE_ERROR(unsigned int); + DECODE_DEBUG(unsigned int, u); + break; + case _C_SHT: + if ([stream readFormat:DECODER_FORMAT(short,hd), + &tmpname, (short*)d] != 2) + DECODE_ERROR(short); + DECODE_DEBUG(short, d); + break; + case _C_USHT: + if ([stream readFormat:DECODER_FORMAT(unsigned short,hu), + &tmpname, (unsigned short*)d] != 2) + DECODE_ERROR(unsigned short); + DECODE_DEBUG(unsigned short, u); + break; + case _C_CHR: + { + unsigned tmp; + if ([stream readFormat:" <%a[^>]> (char) = %*c (%x) \n", + &tmpname, &tmp] != 2) + DECODE_ERROR(char); + *(char*)d = (char)tmp; + DECODE_DEBUG(char, c); + break; + } + case _C_UCHR: + { + unsigned tmp; + if ([stream readFormat:DECODER_FORMAT(unsigned char,x), + &tmpname, &tmp] != 2) + DECODE_ERROR(unsigned char); + *(unsigned char*)d = (unsigned char)tmp; + DECODE_DEBUG(unsigned char, c); + break; + } + case _C_FLT: + if ([stream readFormat:DECODER_FORMAT(float,f), + &tmpname, (float*)d] != 2) + DECODE_ERROR(float); + DECODE_DEBUG(float, f); + break; + case _C_DBL: + if ([stream readFormat:DECODER_FORMAT(double,f), + &tmpname, (double*)d] != 2) + DECODE_ERROR(double); + DECODE_DEBUG(double, f); + break; + case _C_CHARPTR: + if ([stream readFormat:" <%a[^>]> (char*) = \"%a[^\"]\" \n", + &tmpname, (char**)d] != 2) + DECODE_ERROR(char*); + DECODE_DEBUG(char*, s); + break; + default: + [self error:"type %s not yet implemented", type]; + } + if (name && *name) + *name = tmpname; + else + (*objc_free)(tmpname); +} + +- (void) encodeIndent +{ + [stream writeFormat:"%*s {\n", indentation, ""]; + indentation += 2; +} + +- (void) encodeUnindent +{ + indentation -= 2; + [stream writeFormat:"%*s }\n", indentation, ""]; +} + +- (void) decodeIndent +{ + char *line; + char *lp; + lp = line = [stream readLine]; + while (*lp == ' ') lp++; + if (*lp != '{') + [self error:"bad indent format, got \"%s\"", line]; +} + +- (void) decodeUnindent +{ + char *line; + char *lp; + lp = line = [stream readLine]; + while (*lp == ' ') lp++; + if (*lp != '}') + [self error:"bad unindent format, got \"%s\"", line]; +} + +- (void) encodeName: (const char*)n +{ + [stream writeFormat:"%*s<%s>\n", indentation, "", n]; +} + +/* Buffer is malloc'ed */ +- (void) decodeName: (const char**)n +{ + if (n) + { + if ([stream readFormat:" <%a[^>]> \n", n] != 1) + [self error:"bad format"]; + if (debug_textcoder) + fprintf(stderr, "got name <%s>\n", *n); + } + else + { + [stream readFormat:" <%*[^>]> \n"]; + } +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +@end diff --git a/Source/Time.m b/Source/Time.m new file mode 100644 index 000000000..e47c26120 --- /dev/null +++ b/Source/Time.m @@ -0,0 +1,366 @@ +/* Implementation of Objective-C Time object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#if HAVE_SYS_RUSAGE_H +#include +#elif HAVE_UCBINCLUDE_SYS_RESOURCE_H +#include +#endif + +/* There are several places where I need to deal with tz more intelligently */ +/* I should allow customization of a strftime() format string for printing. */ + +/* tmp for passing to gettimeofday() */ +static struct timeval _Time_tv; +static struct timezone _Time_tz; + +id dayNames; +id monthNames; + +@implementation Time + ++ initialize +{ + if (self == [Time class]) + { + [self setVersion:0]; /* beta release */ + /* We should substitute this with a way to make internationalization + more easy. */ + /* Should these indeces start at 1? I think that would be ugly. */ + /* We could switch these to Dictionary's if we want */ + dayNames = [[Array alloc] initWithType:@encode(char*) capacity:7]; + [dayNames putElement:"Monday" atKey:0]; + [dayNames putElement:"Tuesday" atKey:1]; + [dayNames putElement:"Wednesday" atKey:2]; + [dayNames putElement:"Thursday" atKey:3]; + [dayNames putElement:"Friday" atKey:4]; + [dayNames putElement:"Saturday" atKey:5]; + [dayNames putElement:"Sunday" atKey:6]; + monthNames = [[Array alloc] initWithType:@encode(char*) capacity:12]; + [monthNames putElement:"January" atKey:0]; + [monthNames putElement:"February" atKey:1]; + [monthNames putElement:"March" atKey:2]; + [monthNames putElement:"April" atKey:3]; + [monthNames putElement:"May" atKey:4]; + [monthNames putElement:"June" atKey:5]; + [monthNames putElement:"July" atKey:6]; + [monthNames putElement:"August" atKey:7]; + [monthNames putElement:"September" atKey:8]; + [monthNames putElement:"October" atKey:9]; + [monthNames putElement:"November" atKey:10]; + [monthNames putElement:"December" atKey:11]; + } + return self; +} + ++ (long) secondClockValue +{ + gettimeofday(&_Time_tv, &_Time_tz); + return _Time_tv.tv_sec; +} + ++ getClockValueSeconds: (long *)sec microseconds: (long *)usec +{ + gettimeofday(&_Time_tv, &_Time_tz); + *sec = _Time_tv.tv_sec; + *usec = _Time_tv.tv_usec; + return self; +} + ++ (long) millisecondsToRun: (void(*)())aFunc +{ + struct rusage start_ru, end_ru; + + getrusage(RUSAGE_SELF, &start_ru); + (*aFunc)(); + getrusage(RUSAGE_SELF, &end_ru); + return ((end_ru.ru_utime.tv_sec - start_ru.ru_utime.tv_sec + + end_ru.ru_stime.tv_sec - start_ru.ru_stime.tv_sec) * 1000 + +/* xxx disabled for now; not needed? */ +#if 0 && (sun && __svr4__) /* xxx A hack for solaris */ + (end_ru.ru_utime.tv_nsec - start_ru.ru_utime.tv_nsec + + end_ru.ru_stime.tv_nsec - start_ru.ru_stime.tv_nsec) / 1000000); +#else + (end_ru.ru_utime.tv_usec - start_ru.ru_utime.tv_usec + + end_ru.ru_stime.tv_usec - start_ru.ru_stime.tv_usec) / 1000); +#endif + /* should add a warning on overflow. */ +} + ++ getSeconds: (long *)sec microseconds: (long *)usec toRun: (void(*)())aFunc +{ + struct rusage start_ru, end_ru; + + [self notImplemented:_cmd]; + getrusage(RUSAGE_SELF, &start_ru); + (*aFunc)(); + getrusage(RUSAGE_SELF, &end_ru); + + return self; +} + ++ (unsigned) indexOfDayName: (const char *)dayName +{ + return [dayNames keyElementOfElement:(char *)dayName].unsigned_int_u; +} + ++ (const char *) nameOfDayIndex: (unsigned)dayIndex +{ + return [dayNames elementAtKey:dayIndex].char_ptr_u; +} + ++ (unsigned) indexOfMonthName: (const char *)monthName +{ + return [monthNames keyElementOfElement:(char *)monthName].unsigned_int_u; +} + ++ (const char *) nameOfMonthIndex: (unsigned)monthIndex +{ + return [monthNames elementAtKey:monthIndex].char_ptr_u; +} + ++ (unsigned) daysInMonthIndex: (unsigned)monthIndex forYear: (unsigned)year +{ + [self notImplemented:_cmd]; + return 0; +} + ++ (unsigned) daysInYear: (unsigned)year +{ + [self notImplemented:_cmd]; + return 0; +} + ++ (BOOL) leapYear: (unsigned)year +{ + [self notImplemented:_cmd]; + return NO; +} + + +- initNow +{ + [super init]; + gettimeofday(&tv, &tz); + return self; +} + +- initDayIndex: (unsigned)dayIndex + monthIndex: (unsigned)monthIndex + year: (unsigned)year +{ + [self notImplemented:_cmd]; + [super init]; + return self; +} + +- initSeconds: (long)numSeconds microseconds: (long)numMicroseconds +{ + [super init]; + gettimeofday(&tv, &tz); /* to fill tz */ + tv.tv_sec = numSeconds; + tv.tv_usec = numMicroseconds; + return self; +} + +- initSeconds: (long)numSeconds +{ + [super init]; + gettimeofday(&tv, &tz); /* to fill tz */ + tv.tv_sec = numSeconds; + tv.tv_usec = 0; + return self; +} + +- setSeconds: (long)numSeconds microseconds: (long)numMicroseconds +{ + tv.tv_sec = numSeconds; + tv.tv_usec = numMicroseconds; + return self; +} + +- setSeconds: (long)numSeconds +{ + tv.tv_sec = numSeconds; + return self; +} + +- (long) days +{ + return tv.tv_sec / (60 * 60 * 24); +} + +- (long) hours +{ + return tv.tv_sec / (60 * 60); +} + +- (long) minutes +{ + return tv.tv_sec / 60; +} + +- (long) seconds +{ + return tv.tv_sec; +} + +- (long) microseconds; +{ + return tv.tv_usec; +} + + +/* I should do something smart with tz */ + +- addTime: (Time *)aTimeObj +{ + tv.tv_sec += [aTimeObj seconds]; + tv.tv_usec += [aTimeObj microseconds]; + return self; +} + +- addDays: (unsigned)num +{ + tv.tv_sec += num * 60 * 60 * 24; + return self; +} + +- addHours: (unsigned)num +{ + tv.tv_sec += num * 60 * 60; + return self; +} + +- addMinutes: (unsigned)num +{ + tv.tv_sec += num * 60; + return self; +} + +- addSeconds: (unsigned)num +{ + tv.tv_sec += num; + return self; +} + + +- subtractTime: (Time *)aTimeObj +{ + tv.tv_sec -= [aTimeObj seconds]; + tv.tv_usec -= [aTimeObj microseconds]; + return self; +} + +- subtractDays: (unsigned)num +{ + tv.tv_sec -= num * 60 * 60 * 24; + return self; +} + +- subtractHours: (unsigned)num +{ + tv.tv_sec -= num * 60 * 60; + return self; +} + +- subtractMinutes: (unsigned)num +{ + tv.tv_sec -= num * 60; + return self; +} + +- subtractSeconds: (unsigned)num +{ + tv.tv_sec -= num; + return self; +} + + +- printForDebugger +{ + if ([self days]) + printf("%ld days, %ld:%ld:%ld.%3ld\n", + [self days], [self hours], [self minutes], + [self seconds], [self microseconds]); + else + printf("%ld:%ld:%ld.%3ld\n", [self hours], [self minutes], + [self seconds], [self microseconds]); + return self; +} + +- (BOOL) isEqual: anObject +{ + if ([anObject isKindOf:[Time class]] + && [anObject seconds] == tv.tv_sec + && [anObject microseconds] == tv.tv_usec) + return YES; + else + return NO; +} + +- (int) compare: anObject +{ + int diff; + + if (![anObject isKindOf:[Time class]]) + return 17; /* what non-zero should be returned in cases like this? */ + diff = tv.tv_sec - [anObject seconds]; + if (diff) + return diff; + diff = tv.tv_usec - [anObject microseconds]; + return diff; +} + +- (void) encodeWithCoder: (Coder*)anEncoder +{ + [self notImplemented:_cmd]; +} + ++ newWithCoder: (Coder*)aDecoder +{ + [self notImplemented:_cmd]; + return self; +} + +- write: (TypedStream*)aStream +{ + // archive inst vars; + [self notImplemented:_cmd]; + [super write:aStream]; + return self; +} + +- read: (TypedStream*)aStream +{ + // archive inst vars; + [self notImplemented:_cmd]; + [super read:aStream]; + return self; +} + +@end + diff --git a/Source/collhash.c b/Source/collhash.c new file mode 100644 index 000000000..18bcd58c3 --- /dev/null +++ b/Source/collhash.c @@ -0,0 +1,336 @@ +/* Hash tables for Objective C internal structures + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +#include +#include + +#include +#include +#include + +/* These two macros determine when a hash table is full and + by how much it should be expanded respectively. + + These equations are percentages. */ +#define FULLNESS(cache) \ + ((((cache)->size * 75) / 100) <= (cache)->used) +#define EXPANSION(cache) \ + ((cache)->size * 2) + +coll_cache_ptr +coll_hash_new (unsigned int size, + coll_hash_func_type hash_func, + coll_compare_func_type compare_func) +{ + coll_cache_ptr cache; + + /* Pass me a value greater than 0 and a power of 2. */ + assert (size); + assert (!(size & (size - 1))); + + /* Allocate the cache structure. calloc insures + its initialization for default values. */ + cache = (coll_cache_ptr)(*objc_calloc)(1, sizeof (struct coll_cache)); + assert (cache); + + /* Allocate the array of buckets for the cache. + calloc initializes all of the pointers to NULL. */ + cache->node_table + = (coll_node_ptr *)(*objc_calloc)(size, sizeof (coll_node_ptr)); + assert (cache->node_table); + + cache->size = size; + + /* This should work for all processor architectures? */ + cache->mask = (size - 1); + + /* Store the hashing function so that codes can be computed. */ + cache->hash_func = hash_func; + + /* Store the function that compares hash keys to + determine if they are equal. */ + cache->compare_func = compare_func; + + return cache; +} + + +void +coll_hash_delete (coll_cache_ptr cache) +{ + /* + coll_node_ptr node; + void *state = 0; + */ + + /* Purge all key/value pairs from the table. */ + /* was: + while ((node = coll_hash_next (cache, &state))) + coll_hash_remove (cache, node->key); + */ + coll_hash_empty(cache); + + /* Release the array of nodes and the cache itself. */ + (*objc_free) (cache->node_table); + (*objc_free) (cache); +} + +void +coll_hash_empty(coll_cache_ptr cache) +{ + coll_node_ptr node, nextnode; + int i; + + for (i = 0; i < cache->size; i++) + { + node = cache->node_table[i]; + while (node) + { + nextnode = node->next; + (*objc_free)(node); + node = nextnode; + } + cache->node_table[i] = 0; + } + cache->used = 0; +} + +void +coll_hash_add (coll_cache_ptr *cachep, elt key, elt value) +{ + size_t indx = ((*(*cachep)->hash_func)(key)) & (*cachep)->mask; + coll_node_ptr node = + (coll_node_ptr)(*objc_calloc)(1, sizeof (struct coll_cache_node)); + + + assert (node); + + /* Initialize the new node. */ + node->key = key; + node->value = value; + node->next = (*cachep)->node_table[indx]; + + /* Debugging. + Check the list for another key. */ +#if DEBUG + { coll_node_ptr node1 = (*cachep)->node_table[indx]; + + while (node1) { + + assert (node1->key != key); + node1 = node1->next; + } + } +#endif + + /* Install the node as the first element on the list. */ + (*cachep)->node_table[indx] = node; + + /* Bump the number of entries in the cache. */ + ++(*cachep)->used; + + /* Check the hash table's fullness. We're going + to expand if it is above the fullness level. */ + if (FULLNESS (*cachep)) { + + /* The hash table has reached its fullness level. Time to + expand it. + + I'm using a slow method here but is built on other + primitive functions thereby increasing its + correctness. */ + void *state = 0; + coll_node_ptr node1; + coll_cache_ptr new = coll_hash_new (EXPANSION (*cachep), + (*cachep)->hash_func, + (*cachep)->compare_func); + +/* + DEBUG_PRINTF ("Expanding cache %#x from %d to %d\n", + *cachep, (*cachep)->size, new->size); +*/ + + /* Copy the nodes from the first hash table to the new one. */ + while ((node1 = coll_hash_next (*cachep, &state))) + coll_hash_add (&new, node1->key, node1->value); + + /* Trash the old cache. */ + coll_hash_delete (*cachep); + + /* Return a pointer to the new hash table. */ + *cachep = new; + } +} + + +void +coll_hash_remove (coll_cache_ptr cache, elt key) +{ + size_t indx = ((*(cache->hash_func))(key)) & cache->mask; + coll_node_ptr node = cache->node_table[indx]; + + + /* We assume there is an entry in the table. Error if it is not. */ + assert (node); + + /* Special case. First element is the key/value pair to be removed. */ + if (!((*cache->compare_func)(node->key, key))) + { + cache->node_table[indx] = node->next; + (*objc_free) (node); + } + else + { + + /* Otherwise, find the hash entry. */ + coll_node_ptr prev = node; + BOOL removed = NO; + + do + { + + if (!((*cache->compare_func)(node->key, key)) ) + { + prev->next = node->next, removed = YES; + (*objc_free) (node); + } + else + prev = node, node = node->next; + } + while (!removed && node); + assert (removed); + } + + /* Decrement the number of entries in the hash table. */ + --cache->used; +} + +struct coll_hash_state +{ + coll_node_ptr node; + unsigned int last_bucket; +}; + +/* Or should I just pass in a coll_hash_state struct? + It would be a bit less flexible. Less amenable to changes + in structure later... */ + +/* This scheme is just ASKING for memory leaks. Programmers could easily + start an enumeration and then stop before the enumeration is done. + This will leave (struct coll_hash_state) unfree'd! + */ + +coll_node_ptr +coll_hash_next (coll_cache_ptr cache, void** state) +{ +#define HS ((struct coll_hash_state *)*state) + + /* If the scan is being started, then reset */ + if (!(*state)) + { + *state = (void*)(*objc_malloc)(sizeof(struct coll_hash_state)); + HS->node = 0; + HS->last_bucket = 0; + } + + /* If there is a node visited last then check for another + entry in the same bucket; Otherwise step to the next bucket. */ + if (HS->node) { + if (HS->node->next) + { + /* There is a node which follows the last node + returned. Step to that node and retun it. */ + HS->node = HS->node->next; + return HS->node; + } + else + (HS->last_bucket)++; + } + + /* If the list isn't exhausted then search the buckets for + other nodes. */ + if (HS->last_bucket < cache->size) { + /* Scan the remainder of the buckets looking for an entry + at the head of the list. Return the first item found. */ + while (HS->last_bucket < cache->size) + if (cache->node_table[HS->last_bucket]) + { + HS->node = cache->node_table[HS->last_bucket]; + return cache->node_table[HS->last_bucket]; + } + else + (HS->last_bucket)++; + + /* No further nodes were found in the hash table. */ + (*objc_free)(*state); + *state = (void*)0; + return 0; + } else + { + (*objc_free)(*state); + return 0; + } +} + + +/* Given KEY, return corresponding value for it in CACHE. + Return NULL if the KEY is not recorded. */ + +elt +coll_hash_value_for_key (coll_cache_ptr cache, elt key) +{ + coll_node_ptr node = cache->node_table[((*cache->hash_func)(key)) & cache->mask]; + elt retval; + + retval = 0; + if (node) + do { + if (!((*cache->compare_func)(node->key, key))) + retval = node->value; + else + node = node->next; + } while ((retval.void_ptr_u == 0) && node); + + return retval; +} + +/* Something like this would be useful in hash.c, I think. */ + +coll_node_ptr +coll_hash_node_for_key (coll_cache_ptr cache, elt key) +{ + coll_node_ptr node = + cache->node_table[((*cache->hash_func)(key)) & cache->mask]; + + if (node) + do { + if (!((*cache->compare_func)(node->key, key))) + return node; + else + node = node->next; + } while (node); + + return 0; +} diff --git a/Source/eltfuncs.m b/Source/eltfuncs.m new file mode 100644 index 000000000..fb2042b7b --- /dev/null +++ b/Source/eltfuncs.m @@ -0,0 +1,556 @@ +/* Functions for dealing with elt unions + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +/* Is there a better (shorter) way to specify all this junk? */ + +unsigned int +elt_hash_int (elt key) +{ + return (key.int_u); +} + +int +elt_compare_ints (elt k1, elt k2) +{ + if (k1.int_u == k2.int_u) + return 0; + else if (k1.int_u > k2.int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_unsigned_int (elt key) +{ + return (key.unsigned_int_u); +} + +int +elt_compare_unsigned_ints (elt k1, elt k2) +{ + if (k1.unsigned_int_u == k2.unsigned_int_u) + return 0; + else if (k1.unsigned_int_u > k2.unsigned_int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_long_int (elt key) +{ + return ((unsigned int)key.long_int_u); +} + +int +elt_compare_long_ints (elt k1, elt k2) +{ + if (k1.long_int_u == k2.long_int_u) + return 0; + else if (k1.long_int_u > k2.long_int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_unsigned_long_int (elt key) +{ + return ((unsigned int)key.unsigned_long_int_u); +} + +int +elt_compare_unsigned_long_ints (elt k1, elt k2) +{ + if (k1.unsigned_long_int_u == k2.unsigned_long_int_u) + return 0; + else if (k1.unsigned_long_int_u > k2.unsigned_long_int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_char (elt key) +{ + return ((unsigned int)key.char_u); +} + +int +elt_compare_chars (elt k1, elt k2) +{ + if (k1.char_u == k2.char_u) + return 0; + else if (k1.char_u > k2.char_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_unsigned_char (elt key) +{ + return ((unsigned int)key.unsigned_char_u); +} + +int +elt_compare_unsigned_chars (elt k1, elt k2) +{ + if (k1.unsigned_char_u == k2.unsigned_char_u) + return 0; + else if (k1.unsigned_char_u > k2.unsigned_char_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_short (elt key) +{ + return ((unsigned int)key.short_int_u); +} + +int +elt_compare_shorts (elt k1, elt k2) +{ + if (k1.short_int_u == k2.short_int_u) + return 0; + else if (k1.short_int_u > k2.short_int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_unsigned_short (elt key) +{ + return ((unsigned int)key.unsigned_short_int_u); +} + +int +elt_compare_unsigned_shorts (elt k1, elt k2) +{ + if (k1.unsigned_short_int_u == k2.unsigned_short_int_u) + return 0; + else if (k1.unsigned_short_int_u > k2.unsigned_short_int_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_float (elt key) +{ + /* There must be a better hash function for floats than this */ + return ((unsigned int)key.float_u); +} + +int +elt_compare_floats (elt k1, elt k2) +{ + float diff = k1.float_u - k2.float_u; + if (diff == 0) + return 0; + else if (diff > 0) + return 1; + else + return -1; +} + +#if (ELT_INCLUDES_DOUBLE) +unsigned int +elt_hash_double (elt key) +{ + /* There must be a better hash function for doubles than this. + Fix this nonsense: */ + return ((unsigned int)key.double_u); +} + +int +elt_compare_doubles (elt k1, elt k2) +{ + double diff = k1.double_u - k2.double_u; + if (diff == 0) + return 0; + else if (diff > 0) + return 1; + else + return -1; +} +#endif + +int +elt_compare_strings (elt k1, elt k2) +{ + return strcmp (k1.char_ptr_u, k2.char_ptr_u); +} + +unsigned int +elt_hash_string (elt key) +{ + unsigned int ret = 0; + unsigned int ctr = 0; + + while (*key.char_ptr_u) { + ret ^= *key.char_ptr_u++ << ctr; + ctr = (ctr + 1) % sizeof (void *); + } + return ret; +} + +int +elt_compare_void_ptrs (elt k1, elt k2) +{ + if (k1.void_ptr_u == k2.void_ptr_u) + return 0; + else if (k1.void_ptr_u > k2.void_ptr_u) + return 1; + else + return -1; +} + +unsigned int +elt_hash_void_ptr (elt key) +{ + return ((unsigned)key.void_ptr_u) / sizeof(void *); +} + +unsigned int +elt_hash_object (elt key) +{ + return [key.id_u hash]; +} + +int +elt_compare_objects (elt k1, elt k2) +{ + return [k1.id_u compare:k2.id_u]; +} + +int +(*(elt_get_comparison_function(const char *encoding)))(elt,elt) +{ + switch (*encoding) + { + case _C_CHARPTR: + case _C_ATOM: + return elt_compare_strings; + + case _C_ID: + case _C_CLASS: /* isEqual: on classes works well? */ + return elt_compare_objects; + + case _C_PTR: + return elt_compare_void_ptrs; + + case _C_INT: + return elt_compare_ints; + + case _C_SEL: /* is this where this belongs? */ + case _C_UINT: + return elt_compare_unsigned_ints; + + case _C_FLT: + return elt_compare_floats; + +#if ELT_INCLUDES_DOUBLE + case _C_DBL: + return elt_compare_doubles; +#endif + + case _C_LNG: + return elt_compare_long_ints; + + case _C_ULNG: + return elt_compare_unsigned_long_ints; + + case _C_CHR: + return elt_compare_chars; + + case _C_UCHR: + return elt_compare_unsigned_chars; + + case _C_SHT: + return elt_compare_shorts; + + case _C_USHT: + return elt_compare_unsigned_shorts; + + default : + return 0; + } +} + +unsigned int +(*(elt_get_hash_function(const char *encoding)))(elt) +{ + switch (*encoding) + { + case _C_CHARPTR: + case _C_ATOM: + return elt_hash_string; + + case _C_ID: + case _C_CLASS: /* I can send classes isEqual:? */ + return elt_hash_object; + + case _C_PTR: + return elt_hash_void_ptr; + + case _C_INT: + return elt_hash_int; + + case _C_SEL: /* is this where this belongs? */ + case _C_UINT: + return elt_hash_unsigned_int; + + case _C_FLT: + return elt_hash_float; + +#if ELT_INCLUDES_DOUBLE + case _C_DBL: + return elt_hash_double; +#endif + case _C_LNG: + return elt_hash_long_int; + + case _C_ULNG: + return elt_hash_unsigned_long_int; + + case _C_CHR: + return elt_hash_char; + + case _C_UCHR: + return elt_hash_unsigned_char; + + case _C_SHT: + return elt_hash_short; + + case _C_USHT: + return elt_hash_unsigned_short; + + default : + return 0; + } +} + + +static coll_cache_ptr __comp_func_hashtable = 0; +#define INIT_COMP_FUNC_HASHTABLE_SIZE 32 + +static inline void +__init_comp_func_hashtable() +{ + __comp_func_hashtable = + coll_hash_new(INIT_COMP_FUNC_HASHTABLE_SIZE, + (coll_hash_func_type)elt_hash_void_ptr, + (coll_compare_func_type)elt_compare_void_ptrs); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_ints, + @encode(int)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_unsigned_ints, + @encode(unsigned int)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_long_ints, + @encode(long int)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_unsigned_long_ints, + @encode(unsigned long int)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_chars, + @encode(char)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_unsigned_chars, + @encode(unsigned char)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_shorts, + @encode(short)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_unsigned_shorts, + @encode(unsigned short)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_floats, + @encode(float)); +#if (ELT_INCLUDES_DOUBLE) + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_doubles, + @encode(double)); +#endif + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_strings, + @encode(char*)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_void_ptrs, + @encode(void*)); + coll_hash_add(&__comp_func_hashtable, + (void*)elt_compare_objects, + @encode(id)); +} + +const char * +elt_get_encoding(int(*comparison_function)(elt,elt)) +{ + if (!__comp_func_hashtable) + __init_comp_func_hashtable(); + + return (const char *) + coll_hash_value_for_key(__comp_func_hashtable, + (void*)comparison_function).char_ptr_u; +} + + +/* Is this really necessary? Can I count on element members always + starting at the beginning? */ + +extern void *elt_get_ptr_to_member(const char *encoding, elt *anElement) +{ + switch (*encoding) + { + case _C_CHARPTR: + case _C_ATOM: + return &(anElement->char_ptr_u); + + case _C_ID: + case _C_CLASS: + return &(anElement->id_u); + + case _C_PTR: + return &(anElement->void_ptr_u); + + case _C_SEL: + return &(anElement->SEL_u); + + case _C_CHR: + return &(anElement->char_u); + + case _C_UCHR: + return &(anElement->unsigned_char_u); + + case _C_SHT: + return &(anElement->short_int_u); + + case _C_USHT: + return &(anElement->unsigned_short_int_u); + break; + + case _C_INT: + return &(anElement->int_u); + + case _C_UINT: + return &(anElement->unsigned_int_u); + + case _C_LNG: + return &(anElement->long_int_u); + + case _C_ULNG: + return &(anElement->unsigned_long_int_u); + + case _C_FLT: + return &(anElement->float_u); + +#if (ELT_INCLUDES_DOUBLE) + case _C_DBL: + return &(anElement->double_u); +#endif + + default : + return 0; + } +} + +void +elt_fprintf_elt(FILE *fp, const char *encoding, elt anElement) +{ + switch (*encoding) + { + case _C_CHARPTR: + case _C_ATOM: + fprintf(fp, "\"%s\"", anElement.char_ptr_u); + break; + + case _C_ID: + case _C_CLASS: + fprintf(fp, "%s:0x%x", [anElement.id_u name], anElement.unsigned_int_u); + break; + + case _C_PTR: + fprintf(fp, "0x%x", anElement.unsigned_int_u); + break; + + case _C_SEL: + fprintf(fp, "%s", sel_get_name(anElement.SEL_u)); + break; + + case _C_CHR: + fprintf(fp, "%c", anElement.char_u); + break; + + case _C_UCHR: + fprintf(fp, "%c", anElement.unsigned_char_u); + break; + + case _C_SHT: + fprintf(fp, "%d", anElement.short_int_u); + break; + + case _C_USHT: + fprintf(fp, "%d", anElement.unsigned_short_int_u); + break; + + case _C_INT: + fprintf(fp, "%d", anElement.int_u); + break; + + case _C_UINT: + fprintf(fp, "%d", anElement.unsigned_int_u); + break; + + case _C_LNG: + fprintf(fp, "%ld", anElement.long_int_u); + break; + + case _C_ULNG: + fprintf(fp, "%lu", anElement.unsigned_long_int_u); + break; + + case _C_FLT: + fprintf(fp, "%g", anElement.float_u); + break; + +#if (ELT_INCLUDES_DOUBLE) + case _C_DBL: + fprintf(fp, "%g", anElement.double_u); + break; +#endif + + default : + fprintf(fp, "unknown?"); + } +} diff --git a/Source/mframe.m b/Source/mframe.m new file mode 100644 index 000000000..f72e0598c --- /dev/null +++ b/Source/mframe.m @@ -0,0 +1,603 @@ +/* Implementation of functions for dissecting/making method calls + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: Oct 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* These functions can be used for dissecting and making method calls + for many different situations. They are used for distributed + objects; they could also be used to make interfaces between + Objective C and Scheme, Perl, Tcl, whatever... I need to + generalize this stuff a little more to make it useable for an + Invocation class also. */ + +#include +#include +#include +#include +#include + +/* Deal with strrchr: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define index strchr +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + + +/* For encoding and decoding the method arguments, we have to know where + to find things in the "argframe" as returned by __builtin_apply_args. + + For some situations this is obvious just from the selector type + encoding, but structures passed by value cause a problem because some + architectures actually pass these by reference, i.e. use the + structure-value-address mentioned in the gcc/config/_/_.h files. + + These differences are not encoded in the selector types. + + Below is my current guess for which architectures do this. + xxx I really should do this properly by looking at the gcc config values. + + I've also been told that some architectures may pass structures with + sizef(structure) > sizeof(void*) by reference, but pass smaller ones by + value. The code doesn't currently handle that case. + */ + +/* Do we need separate _PASSED_BY_REFERENCE and _RETURNED_BY_REFERENCE? */ + +#if (sparc) || (hppa) || (AM29K) +#define CONNECTION_STRUCTURES_PASSED_BY_REFERENCE 1 +#else +#define CONNECTION_STRUCTURES_PASSED_BY_REFERENCE 0 +#endif + +/* Float and double return values are stored at retframe + 8 bytes + by __builtin_return() + + The retframe consists of 16 bytes. The first 4 are used for ints, + longs, chars, etc. The last 8 are used for floats and doubles. + + xxx This is disgusting. I should get this info from the gcc config + machine description files. xxx + */ +#define FLT_AND_DBL_RETFRAME_OFFSET 8 + +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) + + +/* + Return the number of arguments that the method MTH expects. + Note that all methods need two implicit arguments `self' and + `_cmd'. +*/ +int +method_types_get_number_of_arguments (const char *type) +{ + int i = 0; + while (*type) + { + type = objc_skip_argspec (type); + i += 1; + } + return i - 1; +} + +/* + Return the size of the argument block needed on the stack to invoke + the method MTH. This may be zero, if all arguments are passed in + registers. +*/ + +int +method_types_get_size_of_stack_arguments (const char *type) +{ + type = objc_skip_typespec (type); + return atoi (type); +} + +int +method_types_get_size_of_register_arguments(const char *types) +{ + const char* type = strrchr(types, '+'); + if (type) + return atoi(++type) + sizeof(void*); + else + return 0; +} + +/* To fix temporary bug in method_get_next_argument() on m68k */ +/* xxx Perhaps this isn't working with the NeXT runtime? */ +char* +method_types_get_next_argument (arglist_t argf, + const char **type) +{ + const char *t = objc_skip_argspec (*type); + union { + char *arg_ptr; + char arg_regs[sizeof (char*)]; + } *argframe; + + argframe = (void*)argf; + + if (*t == '\0') + return 0; + + *type = t; + t = objc_skip_typespec (t); + + if (*t == '+') + return argframe->arg_regs + atoi(++t); + else + /* xxx What's going on here? This -8 needed on my 68k NeXT box. */ +#if m68k + return argframe->arg_ptr + (atoi(t) - 8); +#else + return argframe->arg_ptr + atoi(t); +#endif +} + + +/* Returns YES iff there are any outparameters */ +BOOL +dissect_method_call(arglist_t argframe, const char *type, + void (*f)(int,void*,const char*,int)) +{ + const char *tmptype; + unsigned flags; + char *datum; + int argnum; + BOOL out_parameters = NO; + + tmptype = type; + for (datum = method_types_get_next_argument(argframe, &tmptype), argnum=0; + datum; + datum = method_types_get_next_argument(argframe, &tmptype), argnum++) + { + flags = objc_get_type_qualifiers(tmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if (*tmptype == _C_CHARPTR) + { + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*f)(argnum, datum, tmptype, flags); + } + else if (*tmptype == _C_PTR) + { + tmptype++; + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*f)(argnum, *(void**)datum, tmptype, flags); + } + else + { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*f)(argnum, *(void**)datum, tmptype, flags); + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + (*f)(argnum, *(void**)datum, tmptype, flags); +#else + (*f)(argnum, datum, tmptype, flags); +#endif + } + else + { + (*f)(argnum, datum, tmptype, flags); + } + } + return out_parameters; +} + + +void +make_method_call(const char *forward_type, + void(*fd)(int,void*,const char*), + void(*fe)(int,void*,const char*,int)) +{ + const char *type, *tmptype; + const char *ftmptype; + id object; + SEL selector; + IMP imp; + void *retframe; +#if NeXT_runtime + union { + char *arg_ptr; + char arg_regs[sizeof (char*)]; + } *argframe; +#else + arglist_t argframe; +#endif + int stack_argsize; + int reg_argsize; + char *datum; + unsigned flags; + BOOL out_parameters = NO; + int argnum; + + /* get object and selector */ + (*fd)(0, &object, @encode(id)); + assert(object); + + /* @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ + (*fd)(1, &selector, ":"); + assert(selector); + +#if NeXT_runtime + { + Method m; + m = (class_getInstanceMethod(object->isa, selector)); + if (!m) + abort(); + type = m->method_types; + } +#else + type = sel_get_type(selector); +#endif /* NeXT_runtime */ + assert(type); + assert(sel_types_match(forward_type, type)); + + /* Set up argframe */ + stack_argsize = method_types_get_size_of_stack_arguments(type); + reg_argsize = method_types_get_size_of_register_arguments(type); + argframe = (arglist_t) alloca(sizeof(char*) + reg_argsize); + if (stack_argsize) + argframe->arg_ptr = alloca(stack_argsize); + else + argframe->arg_ptr = 0; + + /* decode rest of arguments */ + tmptype = type; + ftmptype = objc_skip_argspec(forward_type); + datum = method_types_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_ID); + *(id*)datum = object; + assert(object); + ftmptype = objc_skip_argspec(ftmptype); + datum = method_types_get_next_argument(argframe, &tmptype); + assert(datum); + assert(*tmptype == _C_SEL); + *(SEL*)datum = selector; + assert(selector); + for (datum = method_types_get_next_argument(argframe, &tmptype), + ftmptype = objc_skip_argspec(ftmptype), argnum = 2; + datum; + datum = method_types_get_next_argument(argframe, &tmptype), + ftmptype = objc_skip_argspec(ftmptype), argnum++) + { + flags = objc_get_type_qualifiers(ftmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if (*tmptype == _C_CHARPTR) + { + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*fd)(argnum, datum, tmptype); + } + else if (*tmptype == _C_PTR) + { + tmptype++; + if ((flags & _F_OUT) || !(flags & _F_IN)) + out_parameters = YES; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* *(void**)datum = alloca(sizeof(void*)); */ + /* xxx or should this be alloca?! + What about inout params? Where do they get freed? */ + *(void**)datum = + (*objc_malloc)(objc_sizeof_type(tmptype)); + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*fd)(argnum, *(void**)datum, tmptype); + } + else + { + /* xxx or should this be alloca?! + What about inout params? Where dothey get freed? */ + *(char**)datum = + (*objc_malloc)(objc_sizeof_type(tmptype)); + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*fd)(argnum, *(void**)datum, tmptype); + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + *(void**)datum = alloca(objc_sizeof_type(tmptype)); + (*fd)(argnum, *(void**)datum, tmptype); +#else + (*fd)(argnum, datum, tmptype); +#endif + } + else + { + (*fd)(argnum, datum, tmptype); + } + } + + /* Call the method */ + imp = objc_msg_lookup(object, selector); + assert(imp); + retframe = __builtin_apply((void(*)(void))imp, + argframe, + stack_argsize); + + /* Return results, if necessary */ + flags = objc_get_type_qualifiers(forward_type); + ftmptype = objc_skip_type_qualifiers(forward_type); + tmptype = objc_skip_type_qualifiers(type); + /* Is this right? Do we also have to check _F_ONEWAY? */ + if (out_parameters || *tmptype != _C_VOID) + { + if (*tmptype != _C_VOID) + { + /* encode return value */ + /* xxx Change this to switch(*tmptype) */ + if (*tmptype == _C_ID) + { + (*fe)(-1, retframe, @encode(id), flags); + } + else if (*tmptype == _C_PTR) + { + tmptype++; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + (*fe)(-1, *(void**)retframe, tmptype, flags); + else + (*fe)(-1, *(void**)retframe, tmptype, flags); + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* xxx these two cases currently the same? */ +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + (*fe)(-1, *(void**)retframe, tmptype, flags); +#else + (*fe)(-1, *(void**)retframe, tmptype, flags); +#endif + } + else if (*tmptype == _C_FLT || *tmptype == _C_DBL) + { + (*fe)(-1, ((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET, + tmptype, flags); + } + else /* Among other types, _C_CHARPTR is handled here */ + { + int retsize = objc_sizeof_type(tmptype); + /* Special case BOOL (and other types smaller than int) + because retframe doesn't actually point to the char */ + /* xxx What about structures smaller than int's that + are passed by reference on true structure reference- + passing architectures? */ + /* xxx Is this the right test? Use sizeof(int*) instead? */ + if (retsize < sizeof(void*)) + { + (*fe)(-1, ((char*)retframe)+sizeof(void*)-retsize, + tmptype, flags); + } + else + { + (*fe)(-1, retframe, tmptype, flags); + } + } + } + + /* encode values returned by reference */ + if (out_parameters) + { + for (datum = method_types_get_next_argument(argframe,&tmptype), + argnum = 1, + ftmptype = objc_skip_argspec(ftmptype); + datum; + datum = method_types_get_next_argument(argframe,&tmptype), + argnum++, + ftmptype = objc_skip_argspec(ftmptype)) + { + flags = objc_get_type_qualifiers(ftmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if ((*tmptype == _C_PTR) + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + tmptype++; + /* xxx These two cases currently the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + (*fe)(argnum, *(void**)datum, tmptype, flags); + } + else + { + (*fe)(argnum, *(void**)datum, tmptype, flags); + } + } + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + (*fe)(argnum, datum, tmptype, flags); + } + } + } + } + return; +} + + +/* In the function that calls this one, be careful about calling more + functions after this one. The memory for the retval_t is alloca'ed. + + Pointer values returned by the method or non-const strings passed + in will now point to newly malloc'ed memory. It is your + responsibility to free it. This is thoroughly disgusting, and will + be fixed as soon as we get rid of the -free method and replace it + with something better. + */ + +retval_t +dissect_method_return(arglist_t argframe, const char *type, + BOOL out_parameters, + void(*f)(int,void*,const char*,int)) +{ + retval_t retframe; + int argnum; + int retsize; + int flags; + const char *tmptype; + void *datum; + + /* get return values, if necessary */ + flags = objc_get_type_qualifiers(type); + tmptype = objc_skip_type_qualifiers(type); + /* xxx What happens with method declared "- (oneway) foo: (out int*)ip;" */ + /* xxx What happens with method declared "- (in char *) bar;" */ + /* Is this right? Do we also have to check _F_ONEWAY? */ + if (out_parameters || *tmptype != _C_VOID) + { + argnum = -1; + if (*tmptype != _C_VOID) + { + /* decode return value */ + retsize = objc_sizeof_type(tmptype); + /* xxx We need to test retsize's less than 4. Also note that + if we return structures using a structure-value-address, we + are potentially alloca'ing much more than we need here. */ + /* xxx Find out about returning structures by reference + on non--structure-value-address machines, and potentially + just always alloca(RETFRAME_SIZE == sizeof(void*)*4) */ + retframe = alloca(MAX(retsize, sizeof(void*)*4)); + /* xxx change this to a switch (*tmptype) */ + if (*tmptype == _C_PTR) + { + tmptype++; + /* xxx these two cases are the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + *(void**)retframe = + (*objc_malloc)(objc_sizeof_type(tmptype)); + (*f)(argnum, *(void**)retframe, tmptype, flags); + } + else + { + *(void**)retframe = + (*objc_malloc)(objc_sizeof_type(tmptype)); + (*f)(argnum, *(void**)retframe, tmptype, flags); + } + } + else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + /* xxx These two cases currently the same */ +#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE + *(void**)retframe = alloca(objc_sizeof_type(tmptype)); + (*f)(argnum, *(void**)retframe, tmptype, flags); +#else + *(void**)retframe = alloca(objc_sizeof_type(tmptype)); + (*f)(argnum, *(void**)retframe, tmptype, flags); +#endif + } + else if (*tmptype == _C_FLT || *tmptype == _C_DBL) + { + (*f)(argnum, ((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET, + tmptype, flags); + } + else /* Among other things, _C_CHARPTR is handled here */ + { + /* int typesize; xxx Use retsize instead! */ + /* xxx was: (typesize = objc_sizeof_type(tmptype)) */ + /* Special case BOOL (and other types smaller than int) + because retframe doesn't actually point to the char */ + /* xxx What about structures smaller than int's that + are passed by reference on true structure reference- + passing architectures? */ + /* xxx Is this the right test? Use sizeof(int*) instead? */ + if (retsize < sizeof(void*)) + { + *(void**)retframe = 0; + (*f)(argnum, ((char*)retframe)+sizeof(void*)-retsize, + tmptype, flags); + } + else + { + (*f)(argnum, retframe, tmptype, flags); + } + } + } + + /* decode values returned by reference */ + if (out_parameters) + { + for (datum = method_types_get_next_argument(argframe, &tmptype), + argnum=0; + datum; + (datum = method_types_get_next_argument(argframe, &tmptype)), + argnum++) + { + flags = objc_get_type_qualifiers(tmptype); + tmptype = objc_skip_type_qualifiers(tmptype); + if (*tmptype == _C_PTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + tmptype++; + /* xxx Note that a (char**) is malloc'ed anew here. + Yucky, or worse than yucky. If the returned string + is smaller than the original, we should just put it + there; if the returned string is bigger, I don't know + what to do. */ + /* xxx These two cases are the same */ + if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B) + { + (*f)(argnum, *(void**)datum, tmptype, flags); + } + else + { + (*f)(argnum, *(void**)datum, tmptype, flags); + } + } + /* __builtin_return can't return structures by value */ + else if (*tmptype == _C_CHARPTR + && ((flags & _F_OUT) || !(flags & _F_IN))) + { + (*f)(argnum, datum, tmptype, flags); + } + } + } + } + else /* void return value */ + { + retframe = alloca(sizeof(void*)); + } + return retframe; +} diff --git a/Source/o_vscanf.c b/Source/o_vscanf.c new file mode 100644 index 000000000..67cda2e6c --- /dev/null +++ b/Source/o_vscanf.c @@ -0,0 +1,617 @@ +/* Implementation of objects_vscanf for GNU Objective C Class Library + + Reworked by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* 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. */ + + + +/* Reworked from glibc by Andrew McCallum: + Fixed bug by adding "*f == 'a'" to type modifier checking. + Declared extern strtod and strtol. + Use function pointer argument to get next character. + Use (*objc_malloc)() instead of malloc() + Use (*objc_realloc)() instead of realloc() + + This is a solution for StdioStream and MemoryStream. + It isn't ideal. Anyone have other suggestions? */ + +/* #include */ +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern double strtod(const char *str, char **ptr); +extern long strtol(const char *str, char** ptr, int base); + +#ifdef __GNUC__ +#define HAVE_LONGLONG +#define LONGLONG long long +#define CONST const +#define LONG_DOUBLE long double +#else +#define LONGLONG long +#define CONST +#endif + + +/* #define inchar() ((c = getc(s)) == EOF ? EOF : (++read_in, c))*/ +#define inchar() ((c = (*inchar_func)(stream)) == EOF ? EOF : (++read_in, c)) + +/* #define conv_error() return ((c == EOF || ungetc(c, s)), done) */ +#define conv_error() return ((c == EOF || ((*unchar_func)(stream,c),c)), done) + +#define input_error() return (done == 0 ? EOF : done) +#define memory_error() return ((errno = ENOMEM), EOF) + + +/* Read formatted input from STREAM according to the format string + FORMAT, using the argument list in ARGPTR. + Return the number of assignments made, or -1 for an input error. */ +int +objects_vscanf (void *stream, + int (*inchar_func)(void*), + void (*unchar_func)(void*,int), + const char *format, va_list argptr) +{ + va_list arg = (va_list) argptr; + + register CONST char *f = format; + register char fc; /* Current character of the format. */ + register size_t done = 0; /* Assignments done. */ + register size_t read_in = 0; /* Chars read in. */ + register int c; /* Last char read. */ + register int do_assign; /* Whether to do an assignment. */ + register int width; /* Maximum field width. */ + + /* Type modifiers. */ + char is_short, is_long, is_long_double; +#ifdef HAVE_LONGLONG + /* We use the `L' modifier for `long long int'. */ +#define is_longlong is_long_double +#else +#define is_longlong 0 +#endif + int malloc_string; /* Args are char ** to be filled in. */ + /* Status for reading F-P nums. */ + char got_dot, got_e; + /* If a [...] is a [^...]. */ + char not_in; + /* Base for integral numbers. */ + int base; + /* Signedness for integral numbers. */ + int number_signed; + /* Integral holding variables. */ + long int num; + unsigned long int unum; + /* Floating-point holding variable. */ + LONG_DOUBLE fp_num; + /* Character-buffer pointer. */ + register char *str, **strptr; + size_t strsize; + /* Workspace. */ + char work[200]; + char *w; /* Pointer into WORK. */ + wchar_t decimal; /* Decimal point character. */ + +#if 0 + if (!__validfp(s) || !s->__mode.__read || format == NULL) + { + errno = EINVAL; + return EOF; + } +#endif + + /* Figure out the decimal point character. */ +#if 0 + if (mbtowc(&decimal, _numeric_info->decimal_point, + strlen(_numeric_info->decimal_point)) <= 0) + decimal = (wchar_t) *_numeric_info->decimal_point; +#else + decimal = '.'; +#endif + + c = inchar(); + + /* Run through the format string. */ + while (*f != '\0') + { + if (!isascii(*f)) + { + /* Non-ASCII, may be a multibyte. */ + int len = mblen(f, strlen(f)); + if (len > 0) + { + while (len-- > 0) + if (c == EOF) + input_error(); + else if (c == *f++) + (void) inchar(); + else + conv_error(); + continue; + } + } + + fc = *f++; + if (fc != '%') + { + /* Characters other than format specs must just match. */ + if (c == EOF) + input_error(); + if (isspace(fc)) + { + /* Whitespace characters match any amount of whitespace. */ + while (isspace (c)) + inchar (); + continue; + } + else if (c == fc) + (void) inchar(); + else + conv_error(); + continue; + } + + /* Check for the assignment-suppressant. */ + if (*f == '*') + { + do_assign = 0; + ++f; + } + else + do_assign = 1; + + /* Find the maximum field width. */ + width = 0; + while (isdigit(*f)) + { + width *= 10; + width += *f++ - '0'; + } + if (width == 0) + width = -1; + + /* Check for type modifiers. */ + is_short = is_long = is_long_double = malloc_string = 0; + while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a') + switch (*f++) + { + case 'h': + /* int's are short int's. */ + is_short = 1; + break; + case 'l': + if (is_long) + /* A double `l' is equivalent to an `L'. */ + is_longlong = 1; + else + /* int's are long int's. */ + is_long = 1; + break; + case 'L': + /* double's are long double's, and int's are long long int's. */ + is_long_double = 1; + break; + case 'a': + /* String conversions (%s, %[) take a `char **' + arg and fill it in with a malloc'd pointer. */ + malloc_string = 1; + break; + } + + /* End of the format string? */ + if (*f == '\0') + conv_error(); + + /* Find the conversion specifier. */ + w = work; + fc = *f++; + if (fc != '[' && fc != 'c' && fc != 'n') + /* Eat whitespace. */ + while (isspace(c)) + (void) inchar(); + switch (fc) + { + case '%': /* Must match a literal '%'. */ + if (c != fc) + conv_error(); + break; + + case 'n': /* Answer number of assignments done. */ + if (do_assign) + *va_arg(arg, int *) = read_in; + break; + + case 'c': /* Match characters. */ + if (do_assign) + { + str = va_arg (arg, char *); + if (str == NULL) + conv_error (); + } + + if (c == EOF) + input_error(); + + if (width == -1) + width = 1; + + if (do_assign) + { + do + *str++ = c; + while (inchar() != EOF && --width > 0); + } + else + while (inchar() != EOF && width > 0) + --width; + + if (do_assign) + ++done; + + break; + + case 's': /* Read a string. */ +#define STRING_ARG \ + if (do_assign) \ + { \ + if (malloc_string) \ + { \ + /* The string is to be stored in a malloc'd buffer. */ \ + strptr = va_arg (arg, char **); \ + if (strptr == NULL) \ + conv_error (); \ + /* Allocate an initial buffer. */ \ + strsize = 100; \ + *strptr = str = (*objc_malloc) (strsize); \ + } \ + else \ + str = va_arg (arg, char *); \ + if (str == NULL) \ + conv_error (); \ + } + STRING_ARG; + + if (c == EOF) + input_error (); + + do + { + if (isspace (c)) + break; +#define STRING_ADD_CHAR(c) \ + if (do_assign) \ + { \ + *str++ = c; \ + if (malloc_string && str == *strptr + strsize) \ + { \ + /* Enlarge the buffer. */ \ + str = (*objc_realloc) (*strptr, strsize * 2); \ + if (str == NULL) \ + { \ + /* Can't allocate that much. Last-ditch effort. */\ + str = (*objc_realloc) (*strptr, strsize + 1); \ + if (str == NULL) \ + { \ + /* We lose. Oh well. \ + Terminate the string and stop converting, \ + so at least we don't swallow any input. */ \ + (*strptr)[strsize] = '\0'; \ + ++done; \ + conv_error (); \ + } \ + else \ + { \ + *strptr = str; \ + str += strsize; \ + ++strsize; \ + } \ + } \ + else \ + { \ + *strptr = str; \ + str += strsize; \ + strsize *= 2; \ + } \ + } \ + } + STRING_ADD_CHAR (c); + } while (inchar () != EOF && (width <= 0 || --width > 0)); + + if (do_assign) + { + *str = '\0'; + ++done; + } + break; + + case 'x': /* Hexadecimal integer. */ + case 'X': /* Ditto. */ + base = 16; + number_signed = 0; + goto number; + + case 'o': /* Octal integer. */ + base = 8; + number_signed = 0; + goto number; + + case 'u': /* Unsigned decimal integer. */ + base = 10; + number_signed = 0; + goto number; + + case 'd': /* Signed decimal integer. */ + base = 10; + number_signed = 1; + goto number; + + case 'i': /* Generic number. */ + base = 0; + number_signed = 1; + + number: + if (c == EOF) + input_error(); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + *w++ = c; + if (width > 0) + --width; + (void) inchar(); + } + + /* Look for a leading indication of base. */ + if (c == '0') + { + if (width > 0) + --width; + *w++ = '0'; + + (void) inchar(); + + if (tolower(c) == 'x') + { + if (base == 0) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + (void) inchar(); + } + } + else if (base == 0) + base = 8; + } + + if (base == 0) + base = 10; + + /* Read the number into WORK. */ + do + { + if (base == 16 ? !isxdigit(c) : + (!isdigit(c) || c - '0' >= base)) + break; + *w++ = c; + if (width > 0) + --width; + } while (inchar() != EOF && width != 0); + + if (w == work || + (w - work == 1 && (work[0] == '+' || work[0] == '-'))) + /* There was on number. */ + conv_error(); + + /* Convert the number. */ + *w = '\0'; + if (number_signed) + num = strtol (work, &w, base); + else +#if HAVE_STRTOUL + unum = strtoul (work, &w, base); +#else + unum = (unsigned long) strtol (work, &w, base); +#endif + if (w == work) + conv_error (); + + if (do_assign) + { + if (! number_signed) + { + if (is_longlong) + *va_arg (arg, unsigned LONGLONG int *) = unum; + else if (is_long) + *va_arg (arg, unsigned long int *) = unum; + else if (is_short) + *va_arg (arg, unsigned short int *) + = (unsigned short int) unum; + else + *va_arg(arg, unsigned int *) = (unsigned int) unum; + } + else + { + if (is_longlong) + *va_arg(arg, LONGLONG int *) = num; + else if (is_long) + *va_arg(arg, long int *) = num; + else if (is_short) + *va_arg(arg, short int *) = (short int) num; + else + *va_arg(arg, int *) = (int) num; + } + ++done; + } + break; + + case 'e': /* Floating-point numbers. */ + case 'E': + case 'f': + case 'g': + case 'G': + if (c == EOF) + input_error(); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + *w++ = c; + if (inchar() == EOF) + /* EOF is only an input error before we read any chars. */ + conv_error(); + if (width > 0) + --width; + } + + got_dot = got_e = 0; + do + { + if (isdigit(c)) + *w++ = c; + else if (got_e && w[-1] == 'e' && (c == '-' || c == '+')) + *w++ = c; + else if (!got_e && tolower(c) == 'e') + { + *w++ = 'e'; + got_e = got_dot = 1; + } + else if (c == decimal && !got_dot) + { + *w++ = c; + got_dot = 1; + } + else + break; + if (width > 0) + --width; + } while (inchar() != EOF && width != 0); + + if (w == work) + conv_error(); + if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e') + conv_error(); + +#ifndef MIB_HACKS + /* Convert the number. */ + *w = '\0'; + fp_num = strtod(work, &w); + if (w == work) + conv_error(); + + if (do_assign) + { + if (is_long_double) + *va_arg(arg, LONG_DOUBLE *) = fp_num; + else if (is_long) + *va_arg(arg, double *) = (double) fp_num; + else + *va_arg(arg, float *) = (float) fp_num; + ++done; + } + break; +#endif /* MIB_HACKS */ + + case '[': /* Character class. */ + STRING_ARG; + + if (c == EOF) + input_error(); + + if (*f == '^') + { + ++f; + not_in = 1; + } + else + not_in = 0; + + while ((fc = *f++) != '\0' && fc != ']') + { + if (fc == '-' && *f != '\0' && *f != ']' && + w > work && w[-1] <= *f) + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ + for (fc = w[-1] + 1; fc < *f; ++fc) + *w++ = fc; + else + /* Add the character to the list. */ + *w++ = fc; + } + if (fc == '\0') + conv_error(); + + *w = '\0'; + unum = read_in; + do + { + if ((strchr (work, c) == NULL) != not_in) + break; + STRING_ADD_CHAR (c); + if (width > 0) + --width; + } while (inchar () != EOF && width != 0); + if (read_in == unum) + conv_error (); + + if (do_assign) + { + *str = '\0'; + ++done; + } + break; + + case 'p': /* Generic pointer. */ + base = 16; + /* A PTR must be the same size as a `long int'. */ + is_long = 1; + goto number; + } + } + + conv_error(); +} diff --git a/Source/objc-gnu2next.m b/Source/objc-gnu2next.m new file mode 100644 index 000000000..7475f19a1 --- /dev/null +++ b/Source/objc-gnu2next.m @@ -0,0 +1,516 @@ +/* Implementation to allow compilation of GNU objc code with NeXT runtime + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Author: Kresten Krab Thorup + Modified by: R. Andrew McCallum + Date: Sep 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#if NeXT_runtime + +/* Deal with strrchr: */ +#if STDC_HEADERS || HAVE_STRING_H +#include +/* An ANSI string.h and pre-ANSI memory.h might conflict. */ +#if !STDC_HEADERS && HAVE_MEMORY_H +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#define index strchr +#define rindex strrchr +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#define bzero(s, n) memset ((s), 0, (n)) +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +/* memory.h and strings.h conflict on some systems. */ +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) + + +static inline int +atoi (const char* str) +{ + int res = 0; + + while (isdigit (*str)) + res *= 10, res += (*str++ - '0'); + + return res; +} + +/* + return the size of an object specified by type +*/ + +int +objc_sizeof_type(const char* type) +{ + switch(*type) { + case _C_ID: + return sizeof(id); + break; + + case _C_CLASS: + return sizeof(Class*); + break; + + case _C_SEL: + return sizeof(SEL); + break; + + case _C_CHR: + return sizeof(char); + break; + + case _C_UCHR: + return sizeof(unsigned char); + break; + + case _C_SHT: + return sizeof(short); + break; + + case _C_USHT: + return sizeof(unsigned short); + break; + + case _C_INT: + return sizeof(int); + break; + + case _C_UINT: + return sizeof(unsigned int); + break; + + case _C_LNG: + return sizeof(long); + break; + + case _C_ULNG: + return sizeof(unsigned long); + break; + + case _C_FLT: + return sizeof(float); + break; + + case _C_DBL: + return sizeof(double); + break; + + case _C_PTR: + case _C_ATOM: + case _C_CHARPTR: + return sizeof(char*); + break; + + case _C_ARY_B: + { + int len = atoi(type+1); + while (isdigit(*++type)); + return len*objc_aligned_size (type); + } + break; + + case _C_STRUCT_B: + { + int acc_size = 0; + int align; + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + while (*type != _C_STRUCT_E) + { + align = objc_alignof_type (type); /* padd to alignment */ + acc_size = ROUND (acc_size, align); + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + return acc_size; + } + + case _C_UNION_B: + { + int max_size = 0; + while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; + while (*type != _C_UNION_E) + { + max_size = MAX (max_size, objc_sizeof_type (type)); + type = objc_skip_typespec (type); + } + return max_size; + } + + default: + abort(); + } +} + + +/* + Return the alignment of an object specified by type +*/ + +int +objc_alignof_type(const char* type) +{ + switch(*type) { + case _C_ID: + return __alignof__(id); + break; + + case _C_CLASS: + return __alignof__(Class*); + break; + + case _C_SEL: + return __alignof__(SEL); + break; + + case _C_CHR: + return __alignof__(char); + break; + + case _C_UCHR: + return __alignof__(unsigned char); + break; + + case _C_SHT: + return __alignof__(short); + break; + + case _C_USHT: + return __alignof__(unsigned short); + break; + + case _C_INT: + return __alignof__(int); + break; + + case _C_UINT: + return __alignof__(unsigned int); + break; + + case _C_LNG: + return __alignof__(long); + break; + + case _C_ULNG: + return __alignof__(unsigned long); + break; + + case _C_FLT: + return __alignof__(float); + break; + + case _C_DBL: + return __alignof__(double); + break; + + case _C_ATOM: + case _C_CHARPTR: + return __alignof__(char*); + break; + + case _C_ARY_B: + while (isdigit(*++type)) /* do nothing */; + return objc_alignof_type (type); + + case _C_STRUCT_B: + { + struct { int x; double y; } fooalign; + while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */; + if (*type != _C_STRUCT_E) + return MAX (objc_alignof_type (type), __alignof__ (fooalign)); + else + return __alignof__ (fooalign); + } + + case _C_UNION_B: + { + int maxalign = 0; + while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; + while (*type != _C_UNION_E) + { + maxalign = MAX (maxalign, objc_alignof_type (type)); + type = objc_skip_typespec (type); + } + return maxalign; + } + + default: + abort(); + } +} + +/* + The aligned size if the size rounded up to the nearest alignment. +*/ + +int +objc_aligned_size (const char* type) +{ + int size = objc_sizeof_type (type); + int align = objc_alignof_type (type); + return ROUND (size, align); +} + +/* + The size rounded up to the nearest integral of the wordsize, taken + to be the size of a void*. +*/ + +int +objc_promoted_size (const char* type) +{ + int size = objc_sizeof_type (type); + int wordsize = sizeof (void*); + + return ROUND (size, wordsize); +} + +/* + Skip type qualifiers. These may eventually precede typespecs + occuring in method prototype encodings. +*/ + +inline const char* +objc_skip_type_qualifiers (const char* type) +{ + while (*type == _C_CONST + || *type == _C_IN + || *type == _C_INOUT + || *type == _C_OUT + || *type == _C_BYCOPY + || *type == _C_ONEWAY) + { + type += 1; + } + return type; +} + + +/* + Skip one typespec element. If the typespec is prepended by type + qualifiers, these are skipped as well. +*/ + +const char* +objc_skip_typespec (const char* type) +{ + type = objc_skip_type_qualifiers (type); + + switch (*type) { + + case _C_ID: + /* An id may be annotated by the actual type if it is known + with the @"ClassName" syntax */ + + if (*++type != '"') + return type; + else + { + while (*++type != '"') /* do nothing */; + return type + 1; + } + + /* The following are one character type codes */ + case _C_CLASS: + case _C_SEL: + case _C_CHR: + case _C_UCHR: + case _C_CHARPTR: + case _C_ATOM: + case _C_SHT: + case _C_USHT: + case _C_INT: + case _C_UINT: + case _C_LNG: + case _C_ULNG: + case _C_FLT: + case _C_DBL: + case _C_VOID: + return ++type; + break; + + case _C_ARY_B: + /* skip digits, typespec and closing ']' */ + + while(isdigit(*++type)); + type = objc_skip_typespec(type); + if (*type == _C_ARY_E) + return ++type; + else + abort(); + + case _C_STRUCT_B: + /* skip name, and elements until closing '}' */ + + while (*type != _C_STRUCT_E && *type++ != '='); + while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); } + return ++type; + + case _C_UNION_B: + /* skip name, and elements until closing ')' */ + + while (*type != _C_UNION_E && *type++ != '='); + while (*type != _C_UNION_E) { type = objc_skip_typespec (type); } + return ++type; + + case _C_PTR: + /* Just skip the following typespec */ + + return objc_skip_typespec (++type); + + default: + abort(); + } +} + +/* + Skip an offset as part of a method encoding. This is prepended by a + '+' if the argument is passed in registers. +*/ +inline const char* +objc_skip_offset (const char* type) +{ + if (*type == '+') type++; + while(isdigit(*++type)); + return type; +} + +/* + Skip an argument specification of a method encoding. +*/ +const char* +objc_skip_argspec (const char* type) +{ + type = objc_skip_typespec (type); + type = objc_skip_offset (type); + return type; +} + +unsigned +objc_get_type_qualifiers (const char* type) +{ + unsigned res = 0; + BOOL flag = YES; + + while (flag) + switch (*type++) + { + case _C_CONST: res |= _F_CONST; break; + case _C_IN: res |= _F_IN; break; + case _C_INOUT: res |= _F_INOUT; break; + case _C_OUT: res |= _F_OUT; break; + case _C_BYCOPY: res |= _F_BYCOPY; break; + case _C_ONEWAY: res |= _F_ONEWAY; break; + default: flag = NO; + } + + return res; +} + + +/* GNU Object.[hm] defines -compare:, NeXT doesn't, libcoll needs it. */ + +@implementation Object (GNUExtensions) +- (int)compare:anotherObject; +{ + if ([self isEqual:anotherObject]) + return 0; + // Ordering objects by their address is pretty useless, + // so subclasses should override this is some useful way. + else if (self > anotherObject) + return 1; + else + return -1; +} +- shouldNotImplement:(SEL)op +{ + return [self error:"should not implement %s", sel_getName (op)]; +} +@end + +#ifdef objc_fatal +#undef objc_fatal +#endif +volatile void +objc_fatal(const char* msg) +{ + write(2, msg, (int)strlen((const char*)msg)); + abort(); +} +void *__objc_xmalloc (unsigned long size) +{ + void* res = (void*) malloc(size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} +void* +__objc_xrealloc(void* mem, size_t size) +{ + void* res = (void*) realloc(mem, size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} +void* +__objc_xcalloc(size_t nelem, size_t size) +{ + void* res = (void*)calloc(nelem, size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} + +/* Returns YES iff t1 and t2 have same method types, but we ignore + the argframe layout */ +BOOL +sel_types_match (const char* t1, const char* t2) +{ + if (!t1 || !t2) + return NO; + while (*t1 && *t2) + { + if (*t1 == '+') t1++; + if (*t2 == '+') t2++; + while (isdigit(*t1)) t1++; + while (isdigit(*t2)) t2++; + /* xxx Remove these next two lines when qualifiers are put in + all selectors, not just Protocol selectors. */ + t1 = objc_skip_type_qualifiers(t1); + t2 = objc_skip_type_qualifiers(t2); + if (!*t1 && !*t2) + return YES; + if (*t1 != *t2) + return NO; + t1++; + t2++; + } + return NO; +} + + + +#endif /* NeXT_runtime */ diff --git a/Source/objc-malloc.c b/Source/objc-malloc.c new file mode 100644 index 000000000..c1add875f --- /dev/null +++ b/Source/objc-malloc.c @@ -0,0 +1,72 @@ +/* Memory allocation support for Objective-C: easy garbage collection. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __STDC__ +#include +#else +#define size_t unsigned long +#endif + +void* +__objc_malloc(size_t size) +{ + void* res = (void*) malloc(size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} + +void* +__objc_realloc(void* mem, size_t size) +{ + void* res = (void*) realloc(mem, size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} + +void* +__objc_calloc(size_t nelem, size_t size) +{ + void* res = (void*) calloc(nelem, size); + if(!res) + objc_fatal("Virtual memory exhausted\n"); + return res; +} + +void +__objc_free (void* mem) +{ + free(mem); +} + +/* We should put + *(void**)obj = 0xdeadface; + into object_dispose(); */ + +/* I do this to make substituting Boehm's Garbage Collector easy. */ +void *(*objc_malloc)(size_t size) = __objc_malloc; +void *(*objc_atomic_malloc)(size_t) = __objc_malloc; +void *(*objc_realloc)(void *optr, size_t size) = __objc_realloc; +void *(*objc_calloc)(size_t nelem, size_t size) = __objc_calloc; +void (*objc_free)(void *optr) = __objc_free; diff --git a/Source/objc/HashTable.h b/Source/objc/HashTable.h new file mode 100644 index 000000000..9235f2581 --- /dev/null +++ b/Source/objc/HashTable.h @@ -0,0 +1,107 @@ +/* Interface for Objective C NeXT-compatible HashTable object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + 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. +*/ + +/****************************************************************** + TODO: + Does not implement methods for archiving itself. + Does not implement -freeKeys:values:. +******************************************************************/ + +#ifndef __HashTable_h_INCLUDE_GNU +#define __HashTable_h_INCLUDE_GNU + +#include +#include + +typedef node_ptr NXHashState; + +@interface HashTable: Object +{ + unsigned count; /* Current number of associations */ + const char *keyDesc; /* Description of keys */ + const char *valueDesc; /* Description of values */ + unsigned _nbBuckets; /* Current size of the array */ + cache_ptr _buckets; /* Data array */ +} +/* We include some instance vars we don't need so we are compatible + with NeXT programs that expect them to be there */ + + +/* Initializing */ + +- init; +- initKeyDesc: (const char *)aKeyDesc; +- initKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc; +- initKeyDesc: (const char *) aKeyDesc + valueDesc: (const char *)aValueDesc + capacity: (unsigned) aCapacity; + +/* Freeing */ + +- free; +- freeObjects; +- freeKeys:(void (*) (void *))keyFunc + values:(void (*) (void *))valueFunc; +- empty; + +/* Copying */ + +- shallowCopy; +- deepen; + +/* Manipulating */ + +- (unsigned)count; +- (BOOL)isKey:(const void *)aKey; +- (void *)valueForKey:(const void *)aKey; +- (void *)insertKey:(const void *)aKey value:(void *)aValue; +- (void *)removeKey:(const void *)aKey; + +/* Iterating */ + +- (NXHashState)initState; +- (BOOL)nextState:(NXHashState *)aState + key:(const void **)aKey + value:(void **)aValue; + +/* Archiving */ + +- read: (TypedStream*)aStream; +- write: (TypedStream*)aStream; + +/* Old-style creation */ + ++ newKeyDesc: (const char *)aKeyDesc; ++ newKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc; ++ newKeyDesc:(const char *)aKeyDesc + valueDesc:(const char *)aValueDesc + capacity:(unsigned)aCapacity; + +/* Sending messages to elements of the hashtable */ + +- makeObjectsPerform:(SEL)aSel; +- makeObjectsPerform:(SEL)aSel with:anObject; + +@end + +#endif /* __HashTable_h_INCLUDE_GNU */ diff --git a/Source/objc/List.h b/Source/objc/List.h new file mode 100644 index 000000000..c0503a7a0 --- /dev/null +++ b/Source/objc/List.h @@ -0,0 +1,103 @@ +/* Interface for Objective-C NeXT-compatible List object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + 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. +*/ + +#ifndef __List_h_INCLUDE_GNU +#define __List_h_INCLUDE_GNU + +#include + +@interface List : Object +{ + @public + id *dataPtr; /* data of the List object */ + unsigned numElements; /* Actual number of elements */ + unsigned maxElements; /* Total allocated elements */ +} + +/* Creating, copying, freeing */ + +- free; +- freeObjects; +- shallowCopy; +- deepen; + +/* Initializing */ + +- init; +- initCount:(unsigned)numSlots; + +/* Comparing two lists */ + +- (BOOL)isEqual: anObject; + +/* Managing the storage capacity */ + +- (unsigned)capacity; +- setAvailableCapacity:(unsigned)numSlots; + +/* Manipulating objects by index */ + +- (unsigned)count; +- objectAt:(unsigned)index; +- lastObject; +- addObject:anObject; +- insertObject:anObject at:(unsigned)index; +- removeObjectAt:(unsigned)index; +- removeLastObject; +- replaceObjectAt:(unsigned)index with:newObject; +- appendList: (List *)otherList; + +/* Manipulating objects by id */ + +- (unsigned)indexOf:anObject; +- addObjectIfAbsent:anObject; +- removeObject:anObject; +- replaceObject:anObject with:newObject; + +/* Emptying the list */ + +- empty; + +/* Archiving */ + +- read: (TypedStream*)aStream; +- write: (TypedStream*)aStream; + +/* Sending messages to elements of the list */ + +- makeObjectsPerform:(SEL)aSel; +- makeObjectsPerform:(SEL)aSel with:anObject; + +/* old-style creation */ + ++ newCount:(unsigned)numSlots; + +@end + +typedef struct { + @defs(List) +} NXListId; + +#define NX_ADDRESS(x) (((NXListId *)(x))->dataPtr) + +#define NX_NOT_IN_LIST 0xffffffff + +#endif /* __List_h_INCLUDE_GNU */ diff --git a/Source/objc/NXStringTable.h b/Source/objc/NXStringTable.h new file mode 100644 index 000000000..3b08e4ba0 --- /dev/null +++ b/Source/objc/NXStringTable.h @@ -0,0 +1,54 @@ +/* Interface for Objective C NeXT-compatible NXStringTable object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Adam Fedor + + This file is part of the GNU Objective-C Collection 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + StringTable.h - Hash table for strings in the NeXT StringTable style + + $Id$ +*/ + +#ifndef __NXStringTable_h_INCLUDE_GNU +#define __NXStringTable_h_INCLUDE_GNU + +#include + +#define MAX_NXSTRINGTABLE_LENGTH 1024 + +@interface NXStringTable: HashTable + +- init; + +- (const char *)valueForStringKey:(const char *)aString; + +- readFromStream:(FILE *)stream; +- readFromFile:(const char *)fileName; + +- writeToStream:(FILE *)stream; +- writeToFile:(const char *)fileName; + +@end + +static inline const char *STRVAL(NXStringTable *table, const char *key) { + return [table valueForStringKey:key]; +} + +#endif /* __NXStringTable_h_INCLUDE_GNU */ diff --git a/Source/objc/Storage.h b/Source/objc/Storage.h new file mode 100644 index 000000000..5fd05f420 --- /dev/null +++ b/Source/objc/Storage.h @@ -0,0 +1,85 @@ +/* Interface for Objective C NeXT-compatible Storage object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/****************************************************************** + TODO: + Does not implement methods for archiving itself. +******************************************************************/ + +#ifndef __Storage_h_INCLUDE_GNU +#define __Storage_h_INCLUDE_GNU + +#include + +@interface Storage : Object +{ +@public + void *dataPtr; /* data of the Storage object */ + const char *description; /* Element description */ + unsigned numElements; /* Actual number of elements */ + unsigned maxElements; /* Total allocated elements */ + unsigned elementSize; /* Element size */ +} + +/* Creating, freeing, initializing, and emptying */ + +- init; +- initCount:(unsigned)numSlots elementSize:(unsigned)sizeInBytes + description:(const char*)elemDesc; +- free; +- empty; +- shallowCopy; + +/* Manipulating the elements */ + +- (BOOL)isEqual: anObject; +- (const char *)description; +- (unsigned)count; +- (void *)elementAt:(unsigned)index; +- replaceElementAt:(unsigned)index with:(void *)anElement; +- setNumSlots:(unsigned)numSlots; +- setAvailableCapacity:(unsigned)numSlots; +- addElement:(void *)anElement; +- removeLastElement; +- insertElement:(void *)anElement at:(unsigned)index; +- removeElementAt:(unsigned)index; + +/* Archiving */ + +- write:(TypedStream *)stream; +- read:(TypedStream *)stream; + +/* old-style creation */ + ++ new; ++ newCount:(unsigned)count elementSize:(unsigned)sizeInBytes + description:(const char *)descriptor; + +@end + +typedef struct { + @defs(Storage) + } NXStorageId; + + +#endif /* __Storage_h_INCLUDE_GNU */ diff --git a/Source/objc/zone.h b/Source/objc/zone.h new file mode 100644 index 000000000..47ebee18a --- /dev/null +++ b/Source/objc/zone.h @@ -0,0 +1,31 @@ +#ifndef __zone_h_OBJECTS_INCLUDE +#define __zone_h_OBJECTS_INCLUDE + +#include + +typedef struct _NXZone +{ + void *(*realloc)(struct _NXZone *zonep, void *ptr, size_t size); + void *(*malloc)(struct _NXZone *zonep, size_t size); + void (*free)(struct _NXZone *zonep, void *ptr); + void (*destroy)(struct _NXZone *zonep); +} NXZone; + +#define NX_NOZONE ((NXZone *)0) +#define NXZoneMalloc(zonep, size) ((*(zonep)->malloc)(zonep, size)) +#define NXZoneRealloc(zonep, ptr, size) ((*(zonep)->realloc)(zonep, ptr, size)) +#define NXZoneFree(zonep, ptr) ((*(zonep)->free)(zonep, ptr)) +#define NXDestroyZone(zonep) ((*(zonep)->destroy)(zonep)) + +extern NXZone *NXDefaultMallocZone(void); +extern NXZone *NXCreateZone(size_t startSize, size_t granularity, int canFree); +extern NXZone *NXCreateChildZone(NXZone *parentZone, size_t startSize, + size_t granularity, int canFree); +extern void NXMergeZone(NXZone *zonep); +extern void *NXZoneCalloc(NXZone *zonep, size_t numElems, size_t byteSize); +extern NXZone *NXZoneFromPtr(void *ptr); +extern void NXZonePtrInfo(void *ptr); +extern void NXNameZone(NXZone *z, const char *name); +extern int NXMallocCheck(void); + +#endif /* __zone_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Array.h b/Source/objects/Array.h new file mode 100644 index 000000000..6f49482d0 --- /dev/null +++ b/Source/objects/Array.h @@ -0,0 +1,65 @@ +/* Interface for Objective-C Array collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Array_h_INCLUDE_GNU +#define __Array_h_INCLUDE_GNU + +#include +#include + +@interface Array : IndexedCollection +{ + @public + int (*_comparison_function)(elt,elt); + elt *_contents_array; + unsigned int _count; + unsigned int _capacity; + unsigned int _grow_factor; +} + ++ (unsigned) defaultCapacity; ++ (unsigned) defaultGrowFactor; + +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; +- initWithCapacity: (unsigned) aCapacity; + +- setCapacity: (unsigned)newCapacity; +- (unsigned) growFactor; +- setGrowFactor: (unsigned)aNum; + +@end + +#define FOR_ARRAY(ARRAY, ELEMENT_VAR) \ +{ \ + unsigned _FOR_ARRAY_i; \ + for (_FOR_ARRAY_i = 0; \ + _FOR_ARRAY_i < ((Array*)ARRAY)->_count; \ + _FOR_ARRAY_i++) \ + { \ + ELEMENT_VAR = \ + (((Array*)ARRAY)->_contents_array[_FOR_ARRAY_i]); + +#define FOR_ARRAY_END }} + +#endif /* __Array_h_INCLUDE_GNU */ diff --git a/Source/objects/ArrayPrivate.h b/Source/objects/ArrayPrivate.h new file mode 100644 index 000000000..a691a0772 --- /dev/null +++ b/Source/objects/ArrayPrivate.h @@ -0,0 +1,87 @@ +/* Array definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ArrayPrivate_h_INCLUDE_GNU +#define __ArrayPrivate_h_INCLUDE_GNU + +#include +#include + +#define DEFAULT_ARRAY_CAPACITY 2 +#define DEFAULT_ARRAY_GROW_FACTOR 2 + + +/* Routines that help with inserting and removing elements */ + +/* Assumes that _count has already been incremented to make room + for the hole. The data at _contents_array[_count-1] is not part + of the collection). */ +static inline void +makeHoleAt(Array *self, unsigned index) +{ + int i; + + for (i = (self->_count)-1; i > index; i--) + self->_contents_array[i] = self->_contents_array[i-1]; +} + +/* Assumes that _count has not yet been decremented. The data at + _contents_array[_count-1] is part of the collection. */ +static inline void +fillHoleAt(Array *self, unsigned index) +{ + int i; + + for (i = index; i < (self->_count)-1; i++) + self->_contents_array[i] = self->_contents_array[i+1]; +} + +/* These are the only two routines that change the value of the instance + variable _count, except for "-initWithType:capacity:" and "-empty" */ + +/* Should these be methods instead of functions? Doing so would make + them slower. */ + +/* Do this before adding an element */ +static inline void +incrementCount(Array *self) +{ + (self->_count)++; + if (self->_count == self->_capacity) + { + [self setCapacity:(self->_capacity) * self->_grow_factor]; + } +} + +/* Do this after removing an element */ +static inline void +decrementCount(Array *self) +{ + (self->_count)--; + if (self->_count < (self->_capacity) / self->_grow_factor) + { + [self setCapacity:(self->_capacity) / self->_grow_factor]; + } +} + +#endif /* __ArrayPrivate_h_INCLUDE_GNU */ diff --git a/Source/objects/Bag.h b/Source/objects/Bag.h new file mode 100644 index 000000000..4e6a6e679 --- /dev/null +++ b/Source/objects/Bag.h @@ -0,0 +1,63 @@ +/* Interface for Objective-C Bag collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Bag_h_INCLUDE_GNU +#define __Bag_h_INCLUDE_GNU + +#include +#include + +@interface Bag : Set +{ + unsigned int _count; // the number of elements; +} + +// ADDING; +- addObject: newObject withOccurrences: (unsigned)count; + +// REMOVING AND REPLACING; +- removeObject: oldObject occurrences: (unsigned)count; +- removeObject: oldObject occurrences: (unsigned)count + ifAbsentCall: (id(*)(arglist_t))excFunc; + +// TESTING; +- (unsigned) uniqueCount; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING AND FREEING; +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; + +// ADDING; +- addElement: (elt)newElement withOccurrences: (unsigned)count; + +// REMOVING AND REPLACING; +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count; +- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +@end + +#endif /* __Bag_h_INCLUDE_GNU */ diff --git a/Source/objects/BinaryCoder.h b/Source/objects/BinaryCoder.h new file mode 100644 index 000000000..fe47fe406 --- /dev/null +++ b/Source/objects/BinaryCoder.h @@ -0,0 +1,38 @@ +/* Interface for GNU Objective-C binary coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __BinaryCoder_h +#define __BinaryCoder_h + +#include +#include + +@class Stream; + +@interface BinaryCoder : Coder +{ +} + +@end + +#endif /* __BinaryCoder_h */ diff --git a/Source/objects/BinaryTree.h b/Source/objects/BinaryTree.h new file mode 100644 index 000000000..ef35e54cd --- /dev/null +++ b/Source/objects/BinaryTree.h @@ -0,0 +1,75 @@ +/* Interface for Objective-C BinaryTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Binary Tree. + Base class for smarter binary trees. +*/ + +#ifndef __BinaryTree_h_INCLUDE_GNU +#define __BinaryTree_h_INCLUDE_GNU + +#include +#include + +/* The protocol defines the interface to an object + that may be an element in a BinaryTree. +*/ +@protocol BinaryTreeComprising +- leftNode; +- rightNode; +- parentNode; +- setLeftNode: (id )aNode; +- setRightNode: (id )aNode; +- setParentNode: (id )aNode; +@end + +#define NODE_IS_RIGHTCHILD(NODE) (NODE == [[NODE parentNode] rightNode]) +#define NODE_IS_LEFTCHILD(NODE) (NODE == [[NODE parentNode] leftNode]) + +@interface BinaryTree : IndexedCollection +{ + unsigned int _count; + id _contents_root; +} + +- nilNode; +- rootNode; + +- leftmostNodeFromNode: aNode; +- rightmostNodeFromNode: aNode; + +- (unsigned) depthOfNode: aNode; +- (unsigned) heightOfNode: aNode; + +- (unsigned) nodeCountUnderNode: aNode; + +- leftRotateAroundNode: aNode; +- rightRotateAroundNode: aNode; + +- binaryTreePrintForDebugger; + +@end + + +#endif /* __BinaryTree_h_INCLUDE_GNU */ diff --git a/Source/objects/BinaryTreeEltNode.h b/Source/objects/BinaryTreeEltNode.h new file mode 100644 index 000000000..b7912a1e5 --- /dev/null +++ b/Source/objects/BinaryTreeEltNode.h @@ -0,0 +1,36 @@ +/* Interface for Objective-C BinaryTreeEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __BinaryTreeEltNode_h_INCLUDE_GNU +#define __BinaryTreeEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface BinaryTreeEltNode : BinaryTreeNode +#include +@end + + +#endif /* __BinaryTreeEltNode_h_INCLUDE_GNU */ diff --git a/Source/objects/BinaryTreeNode.h b/Source/objects/BinaryTreeNode.h new file mode 100644 index 000000000..2a3d255c8 --- /dev/null +++ b/Source/objects/BinaryTreeNode.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C BinaryTreeNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __BinaryTreeNode_h_INCLUDE_GNU +#define __BinaryTreeNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface BinaryTreeNode : Object +{ + id _left; + id _right; + id _parent; +} +@end + + +#endif /* __BinaryTreeNode_h_INCLUDE_GNU */ diff --git a/Source/objects/CircularArray.h b/Source/objects/CircularArray.h new file mode 100644 index 000000000..b4b138b84 --- /dev/null +++ b/Source/objects/CircularArray.h @@ -0,0 +1,38 @@ +/* Interface for Objective-C CircularArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CircularArray_h_INCLUDE_GNU +#define __CircularArray_h_INCLUDE_GNU + +#include +#include + +@interface CircularArray : Array +{ + @public + unsigned int _start_index; +} + +@end + +#endif /* __CircularArray_h_INCLUDE_GNU */ diff --git a/Source/objects/CircularArrayPrivate.h b/Source/objects/CircularArrayPrivate.h new file mode 100644 index 000000000..67f0e5580 --- /dev/null +++ b/Source/objects/CircularArrayPrivate.h @@ -0,0 +1,75 @@ +/* CircularArray definitions for the use of subclass implementations + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CircularArrayPrivate_h_INCLUDE_GNU +#define __CircularArrayPrivate_h_INCLUDE_GNU + +#include +#include + +#define CIRCULAR_TO_BASIC(INDEX) \ + ((INDEX + self->_start_index) % self->_capacity) + +#define BASIC_TO_CIRCULAR(INDEX) \ + ((INDEX + self->_capacity - self->_start_index) % self->_capacity) + +#define NEXT_CIRCULAR_INDEX(INDEX) \ + ((INDEX + 1) % self->_capacity) + +#define PREV_CIRCULAR_INDEX(INDEX) \ + ((INDEX + self->_capacity - 1) % self->_capacity) + +static inline void +circularMakeHoleAt(CircularArray *self, unsigned basicIndex) +{ + int i; + if (self->_start_index && basicIndex > self->_start_index) + { + for (i = self->_start_index; i < basicIndex; i++) + self->_contents_array[i-1] = self->_contents_array[i]; + } + else + { + for (i = CIRCULAR_TO_BASIC(self->_count-1); i >= basicIndex; i--) + self->_contents_array[i+1] = self->_contents_array[i]; + } + /* This is never called with _count == 0 */ +} + +static inline void +circularFillHoleAt(CircularArray *self, unsigned basicIndex) +{ + int i; + if (basicIndex > self->_start_index) + { + for (i = basicIndex; i > self->_start_index; i--) + self->_contents_array[i] = self->_contents_array[i-1]; + } + else + { + for (i = basicIndex; i < CIRCULAR_TO_BASIC(self->_count-1); i++) + self->_contents_array[i] = self->_contents_array[i+1]; + } +} + +#endif /* __CircularArrayPrivate_h_INCLUDE_GNU */ diff --git a/Source/objects/Coder.h b/Source/objects/Coder.h new file mode 100644 index 000000000..1005810e9 --- /dev/null +++ b/Source/objects/Coder.h @@ -0,0 +1,158 @@ +/* Interface for GNU Objective-C coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Coder_h +#define __Coder_h + +#include +#include + +@class Stream; +@class Dictionary; +@class Stack; + +@interface Coder : Object +{ + int format_version; + int concrete_format_version; + Stream *stream; + BOOL is_decoding; + BOOL doing_root_object; + Dictionary *object_table; /* read/written objects */ + Dictionary *const_ptr_table; /* read/written const *'s */ + Stack *root_object_tables; /* Stack of Dicts for interconnt'd objs */ + Stack *forward_object_tables; /* Stack of Dictionaries for frwd refs */ +} + ++ (void) setDefaultStreamClass: sc; ++ defaultStreamClass; ++ setDebugging: (BOOL)f; + +- initEncodingOnStream: (Stream *)s; +- initDecodingOnStream: (Stream *)s; +- initEncoding; +- initDecoding; +- init; + +- free; +- (BOOL) isDecoding; + +- (void) encodeValueOfType: (const char*)type + at: (const void*)d + withName: (const char *)name; +- (void) decodeValueOfType: (const char*)type + at: (void*)d + withName: (const char **)namePtr; + +- (void) encodeWithName: (const char *)name + valuesOfTypes: (const char *)types, ...; +- (void) decodeWithName: (const char **)name + valuesOfTypes: (const char *)types, ...; + +- (void) encodeArrayOfType: (const char *)type + at: (const void *)d + count: (unsigned)c + withName: (const char *)name; +- (void) decodeArrayOfType: (const char *)type + at: (void *)d + count: (unsigned *)c + withName: (const char **)name; + +- (void) encodeObject: anObj + withName: (const char *)name; +- (void) encodeObjectBycopy: anObj + withName: (const char *)name; +- (void) decodeObjectAt: (id*)anObjPtr + withName: (const char **)name; + +- (void) encodeRootObject: anObj + withName: (const char *)name; +- (void) encodeObjectReference: anObj + withName: (const char *)name; +- (void) startEncodingInterconnectedObjects; +- (void) finishEncodingInterconnectedObjects; +- (void) startDecodingInterconnectedObjects; +- (void) finishDecodingInterconnectedObjects; + +- (void) encodeAtomicString: (const char*)sp + withName: (const char*)name; +- (const char *) decodeAtomicStringWithName: (const char **)name; + +- decodeClass; +- (void) encodeClass: aClass; + +/* For inserting a name into a TextCoder stream */ +- (void) encodeName: (const char*)n; +- (void) decodeName: (const char**)n; + +/* For subclasses that want to keep track of recursion */ +- (void) encodeIndent; +- (void) encodeUnindent; +- (void) decodeIndent; +- (void) decodeUnindent; + +/* Implemented by concrete subclasses */ +- (void) encodeValueOfSimpleType: (const char*)type + at: (const void*)d + withName: (const char *)name; +- (void) decodeValueOfSimpleType: (const char*)type + at: (void*)d + withName: (const char **)namePtr; +- (void) encodeBytes: (const char *)b + count: (unsigned)c + withName: (const char *)name; +- (void) decodeBytes: (char *)b + count: (unsigned*)c + withName: (const char **)name; + +- (int) coderFormatVersion; +- (int) coderConcreteFormatVersion; + +- (void) resetCoder; /* xxx remove this? */ + +- doInitOnStream: (Stream *)s isDecoding: (BOOL)f; +/* Internal designated initializer. Override it, but don't call it yourself. + This method name may change. */ + ++ (int) coderFormatVersion; ++ (int) coderConcreteFormatVersion; ++ (const char *) coderSignature; + +@end + +@interface Object (CoderAdditions) +- (void) encodeWithCoder: (Coder*)anEncoder; ++ newWithCoder: (Coder*)aDecoder; + +/* These methods here temporarily until ObjC runtime category bug fixed */ +- classForConnectedCoder:aRmc; ++ (void) encodeObject: anObject withConnectedCoder: aRmc; +- (id) retain; +- (void) release; +- (void) dealloc; +- (unsigned) retainCount; +- (BOOL) isProxy; + +@end + +#endif __Coder_h diff --git a/Source/objects/Coding.h b/Source/objects/Coding.h new file mode 100644 index 000000000..a8689f3a5 --- /dev/null +++ b/Source/objects/Coding.h @@ -0,0 +1,57 @@ +/* Protocol for GNU Objective-C objects that can write/read to a coder + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Coding_h +#define __Coding_h + +#include + +@class Coder; + +@protocol Coding + +- (void) encodeWithCoder: (Coder*)anEncoder; ++ newWithCoder: (Coder*)aDecoder; + +/* NOTE: + + This is +newWithCoder: and not -initWithCoder: because many classes + keep track of their instances and only allow one instance of each + configuration. For example, see the designated initializers of + SocketPort, Connection, and Proxy. + + Making this +new.. instead of -init.. prevents us from having to + waste the effort of allocating space for an object to be decoded, + then immediately deallocating that space because we're just + returning a pre-existing object. + + I also like it because it makes very clear that this method is + expected to return the decoded object. This requirement would have + also been present in an -init... implementation, but the + requirement may not have been 100 percent clear by the method name. + + -mccallum */ + +@end + +#endif /* __Coding_h */ diff --git a/Source/objects/Collecting.h b/Source/objects/Collecting.h new file mode 100644 index 000000000..918db0c70 --- /dev/null +++ b/Source/objects/Collecting.h @@ -0,0 +1,195 @@ +/* Protocol for Objective-C objects that hold collections of elements. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol is root of the collection protocol heirarchy. + + The protocol defines the most general interface to a + collection of elements. Elements can be added, removed, and replaced. + The contents can be tested, enumerated, and enumerated through various + filters. Elements may be objects, or any C type included in the + "elt" union given in elt.h, but all elements of a collection must be of + the same C type. +*/ + +#ifndef __Collecting_h_INCLUDE_GNU +#define __Collecting_h_INCLUDE_GNU + +#include +#include +#include + +@protocol Collecting + +// INITIALIZING; +- init; +- initWithContentsOf: (id )aCollection; + +// FREEING; +- free; +- freeObjects; + +// ADDING; +- addObject: newObject; +- addObjectIfAbsent: newObject; +- addContentsOf: (id )aCollection; +- addContentsOfIfAbsent: (id )aCollection; +- addObjectsCount: (unsigned)count, ...; + +// REMOVING; +- removeObject: oldObject; +- removeObject: oldObject ifAbsentCall: (id(*)(arglist_t))excFunc; +- removeAllOccurrencesOfObject: oldObject; +- removeContentsIn: (id )aCollection; +- removeContentsNotIn: (id )aCollection; +- uniqueContents; +- empty; + +// REPLACING; +- replaceObject: oldObject with: newObject; +- replaceObject: oldObject with: newObject + ifAbsentCall:(id(*)(arglist_t))excFunc; +- replaceAllOccurrencesOfObject: oldObject with: newObject; + +// TESTING; +- (BOOL) isEmpty; +- (BOOL) includesObject: anObject; +- (BOOL) isSubsetOf: (id )aCollection; +- (BOOL) isDisjointFrom: (id )aCollection; +- (int) compare: anObject; +- (BOOL) isEqual: anObject; +- (BOOL) contentsEqual: (id )aCollection; +- (unsigned) count; +- (unsigned) occurrencesOfObject: anObject; +- (BOOL) trueForAllObjectsByCalling: (BOOL(*)(id))aFunc; +- (BOOL) trueForAnyObjectsByCalling: (BOOL(*)(id))aFunc; +- detectObjectByCalling: (BOOL(*)(id))aFunc; +- detectObjectByCalling: (BOOL(*)(id))aFunc + ifNoneCall: (id(*)(arglist_t))excFunc; +- maxObject; +- maxObjectByCalling: (int(*)(id,id))aFunc; +- minObject; +- minObjectByCalling: (int(*)(id,id))aFunc; + +// ENUMERATING +- (void*) newEnumState; +- (BOOL) getNextObject:(id *)anObjectPtr withEnumState: (void**)enumState; +- freeEnumState: (void**)enumState; +- withObjectsCall: (void(*)(id))aFunc; +- withObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; +- injectObject: initialArgObject byCalling:(id(*)(id,id))aFunc; +- makeObjectsPerform: (SEL)aSel; +- makeObjectsPerform: (SEL)aSel with: argObject; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeMakeObjectsPerform: (SEL)aSel; +- safeMakeObjectsPerform: (SEL)aSel with: argObject; +- safeWithObjectsCall: (void(*)(id))aFunc; +- safeWithObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// FILTERED ENUMERATING; +- withObjectsTrueByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc; +- withObjectsFalseByCalling: (BOOL(*)(id))testFunc + call: (void(*)(id))destFunc; +- withObjectsTransformedByCalling: (id(*)(id))transFunc + call: (void(*)(id))destFunc; + +// COPYING +- emptyCopy; +- emptyCopyAs: (id )aCollectionClass; +- shallowCopy; +- shallowCopyAs: (id )aCollectionClass; +- copy; +- copyAs: (id )aCollectionClass; +- species; + +// ARCHIVING; +- write: (TypedStream*)aStream; +- read: (TypedStream*)aStream; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING; +- initWithType:(const char *)contentEncoding; + +// ADDING; +- addElement: (elt)newElement; +- addElementIfAbsent: (elt)newElement; +- addElementsCount: (unsigned)count, ...; + +// REMOVING; +- (elt) removeElement: (elt)oldElement; +- (elt) removeElement: (elt)oldElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; +- removeAllOccurrencesOfElement: (elt)oldElement; + +// REPLACING; +- (elt) replaceElement: (elt)oldElement with: (elt)newElement; +- (elt) replaceElement: (elt)oldElement with: (elt)newElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; +- replaceAllOccurrencesOfElement: (elt)oldElement with: (elt)newElement; + +// TESTING; +- (BOOL) includesElement: (elt)anElement; +- (unsigned) occurrencesOfElement: (elt)anElement; +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc; +- (elt) detectElementByCalling: (BOOL(*)(elt))aFunc + ifNoneCall: (elt(*)(arglist_t))excFunc; +- (elt) maxElement; +- (elt) maxElementByCalling: (int(*)(elt,elt))aFunc; +- (elt) minElement; +- (elt) minElementByCalling: (int(*)(elt,elt))aFunc; +- (BOOL) trueForAllElementsByCalling: (BOOL(*)(elt))aFunc; +- (BOOL) trueForAnyElementsByCalling: (BOOL(*)(elt))aFunc; +- (const char *) contentType; +- (BOOL) contentsAreObjects; +- (int(*)(elt,elt)) comparisonFunction; + +// ENUMERATING; +- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState; +- withElementsCall: (void(*)(elt))aFunc; +- withElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag; +- (elt) injectElement: (elt)initialElement byCalling: (elt(*)(elt,elt))aFunc; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithElementsCall: (void(*)(elt))aFunc; +- safeWithElementsCall: (void(*)(elt))aFunc whileTrue: (BOOL*)flag; + +// FILTERED ENUMERATING; +- withElementsTrueByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc; +- withElementsFalseByCalling: (BOOL(*)(elt))testFunc + call: (void(*)(elt))destFunc; +- withElementsTransformedByCalling: (elt(*)(elt))transFunc + call: (void(*)(elt))destFunc; + + +// BE SURE WE HAVE THESE METHODS NORMALLY PROVIDED BY Object; ++ alloc; +- (BOOL) respondsTo: (SEL)aSel; +- (BOOL) conformsTo: aProtocolObject; + +@end + +#endif /* __Collecting_h_INCLUDE_GNU */ diff --git a/Source/objects/Collection.h b/Source/objects/Collection.h new file mode 100644 index 000000000..71b2eb4a7 --- /dev/null +++ b/Source/objects/Collection.h @@ -0,0 +1,92 @@ +/* Interface for Objective-C Collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is the abstract superclass that satisfies the Collecting + protocol, without using any instance variables. +*/ + +#ifndef __Collection_h_INCLUDE_GNU +#define __Collection_h_INCLUDE_GNU + +#include +#include +#include +#include +#include +#include +#include + +@interface Collection : Object +{ +} + ++ initialize; + +- printElement: (elt)anElement; +- printForDebugger; + +@end + +// #warning fix this macro +#define FOR_COLL(ACOLL, ELT) \ +{ \ + void *_es = [ACOLL initEnumState]; \ + while ([ACOLL getNextElement:&(ELT) withEnumState:&_es]) \ + { + +#define FOR_COLL_END \ + } \ + [ACOLL freeEnumState:_es]; \ +} + +/* The only subclassResponsibilities in Collection are: + + addElement: + removeElement: + getNextElement:withEnumState: + empty + + But subclasses may need to override the following for correctness: + + contentType + comparisonFunction + + but subclasses will want to override others as well in order to + increase efficiency, especially: + + count + + and perhaps: + + includesElement: + occurrencesOfElement: + uniqueContents + withElementsCall:whileTrue: + withElementsCall: + isEmpty + freeObjects + +*/ + +#endif /* __Collection_h_INCLUDE_GNU */ + diff --git a/Source/objects/CollectionPrivate.h b/Source/objects/CollectionPrivate.h new file mode 100644 index 000000000..abf841cd8 --- /dev/null +++ b/Source/objects/CollectionPrivate.h @@ -0,0 +1,92 @@ +/* Collection definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CollectionPrivate_h_INCLUDE_GNU +#define __CollectionPrivate_h_INCLUDE_GNU + +#include +#include + +@interface Collection (ArchivingHelpers) +/* These methods should never be called except in order inside + -write: and -read: */ +- _writeInit: (TypedStream*)aStream; +- _readInit: (TypedStream*)aStream; +- _writeContents: (TypedStream*)aStream; +- _readContents: (TypedStream*)aStream; + +/* The Coding versions of the above */ +- (void) _encodeCollectionWithCoder: (Coder*) aCoder; ++ _newCollectionWithCoder: (Coder*) aCoder; +- (void) _encodeContentsWithCoder: (Coder*)aCoder; +- (void) _decodeContentsWithCoder: (Coder*)aCoder; +@end + + +/* To be used inside methods for getting the element comparison function. + This macro could be redefined when the comparison function is an + instance variable or is fixed. + I'm wondering if I should put _comparison_function back as an instance + variable in Collection. */ +#define COMPARISON_FUNCTION [self comparisonFunction] + +/* Use this for comparing elements in your implementation. */ +#define COMPARE_ELEMENTS(ELT1, ELT2) \ + ((*COMPARISON_FUNCTION)(ELT1, ELT2)) + +#define ELEMENTS_EQUAL(ELT1, ELT2) \ + (COMPARE_ELEMENTS(ELT1, ELT2) == 0) + +#define ENCODING_IS_OBJECT(ENCODING) \ + ((*(ENCODING) == _C_ID) || (*(ENCODING) == _C_CLASS)) + +/* To be used inside a method for determining if the contents are objects */ +#define CONTAINS_OBJECTS \ + (ENCODING_IS_OBJECT([self contentType])) + + +/* Error Handling */ + +#define RETURN_BY_CALLING_EXCEPTION_FUNCTION(FUNC) \ +return (*FUNC)(__builtin_apply_args()) + + +/* To be used inside a method for making sure the contents are objects. + typeof(DEFAULT_ERROR_RETURN) must be the same type as the method + returns. */ +#define CHECK_CONTAINS_OBJECTS_ERROR() \ +({if (!(CONTAINS_OBJECTS)) \ +{ \ + [self error:"in %s, requires object contents", sel_get_name(_cmd)]; \ +}}) + +/* To be used inside a method whenever a particular element isn't found */ +#define ELEMENT_NOT_FOUND_ERROR(AN_ELEMENT) \ +([self error:"in %s, element not found.", sel_get_name(_cmd)]) + +/* To be used inside a method whenever there is no element matching the + needed criteria */ +#define NO_ELEMENT_FOUND_ERROR() \ +([self error:"in %s, no element found.", sel_get_name(_cmd)]) + +#endif /* __CollectionPrivate_h_INCLUDE_GNU */ diff --git a/Source/objects/ConnectedCoder.h b/Source/objects/ConnectedCoder.h new file mode 100644 index 000000000..2f6df13a4 --- /dev/null +++ b/Source/objects/ConnectedCoder.h @@ -0,0 +1,66 @@ +/* Interface for coder object for distributed objects + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ConnectedCoder_h +#define __ConnectedCoder_h + +#include +#include + +/* ConnectedCoder identifiers */ +#define METHOD_REQUEST 0 +#define METHOD_REPLY 1 +#define ROOTPROXY_REQUEST 2 +#define ROOTPROXY_REPLY 3 +#define CONNECTION_SHUTDOWN 4 +#define METHODTYPE_REQUEST 5 /* these two only needed with NeXT runtime */ +#define METHODTYPE_REPLY 6 + +@class Connection; + +@interface ConnectedCoder : BinaryCoder +{ + Connection *connection; + unsigned sequence_number; + int identifier; + + /* only used for incoming ConnectedCoder's */ + id remotePort; +} + ++ newEncodingWithConnection: (Connection*)c + sequenceNumber: (int)n + identifier: (int)i; ++ newDecodingWithConnection: (Connection*)c + timeout: (int) timeout; +- dismiss; + +- connection; +- (unsigned) sequenceNumber; +- (int) identifier; + +- remotePort; + +@end + +#endif /* __ConnectedCoder_h */ diff --git a/Source/objects/Connection.h b/Source/objects/Connection.h new file mode 100644 index 000000000..9f29d169a --- /dev/null +++ b/Source/objects/Connection.h @@ -0,0 +1,200 @@ +/* Interface for GNU Objective-C connection for remote object messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Connection_h_OBJECTS_INCLUDE +#define __Connection_h_OBJECTS_INCLUDE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +@class Proxy; +@class Port; +@class ConnectedCoder; + +@interface Connection : RetainingNotifier +{ + id delegate; + Port *in_port; + Port *out_port; + unsigned message_count; + Dictionary *local_targets; + Dictionary *remote_proxies; + int in_timeout; + int out_timeout; + id port_class; + int queue_dialog_interruptions; + Dictionary *incoming_const_ptrs; + Dictionary *outgoing_const_ptrs; +} + ++ setDefaultPortClass: aPortClass; ++ defaultProxyClass; ++ setDefaultProxyClass: aClass; ++ (int) defaultOutTimeout; ++ setDefaultOutTimeout: (int)to; ++ (int) defaultInTimeout; ++ setDefaultInTimeout: (int)to; +/* Setting and getting class configuration */ + ++ (int) messagesReceived; ++ (id ) allConnections; ++ (unsigned) connectionsCount; ++ (unsigned) connectionsCountWithInPort: (Port*)aPort; +/* Querying the state of all the connections */ + ++ removeObject: anObj; ++ unregisterForInvalidationNotification: anObj; +/* Use these when you're free'ing an object that may have been vended + or registered for invalidation notification */ + ++ (Connection*) newWithRootObject: anObj; ++ (Connection*) newRegisteringAtName: (const char*)n withRootObject: anObj; +/* Registering your server object on the network. + These methods create a new connection object that must be "run" in order + to start handling requests from clients. + These method names may change when we get the capability to register + ports with names after the ports have been created. */ +/* I want the second method name to clearly indicate that we're not + connecting to a pre-existing registration name, we're registering a + new name, and this method will fail if that name has already been + registered. This is why I don't like "newWithRegisteredName:" --- + it's unclear if we're connecting to another Connection that already + registered with that name. */ + ++ (Proxy*) rootProxyAtName: (const char*)name onHost: (const char*)host; ++ (Proxy*) rootProxyAtName: (const char*)name; ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort; ++ (Proxy*) rootProxyAtPort: (Port*)anOutPort withInPort: (Port*)anInPort; +/* Get a proxy to a remote server object. + A new connection is created if necessary. */ + ++ (Connection*) newForInPort: (Port*)anInPort outPort: (Port*)anOutPort + ancestorConnection: (Connection*)ancestor; +/* This is the designated initializer for the Connection class. + You don't need to call it yourself. */ + +- (void) runConnectionWithTimeout: (int)timeout; +/* Make a connection object start listening for incoming requests. After + `timeout' milliseconds without receiving anything, return. */ + +- (void) runConnection; +/* Same as above, but never time out. */ + +- (id ) proxies; +/* When you get an invalidation notification from a connection, use + this method in order to find out if any of the proxy objects you're + using are going away. */ + +- (Proxy*) rootProxy; +/* If you somehow have a connection to a server, but don't have it's + a proxy to its root object yet, you can use this to get it. */ + +- rootObject; ++ rootObjectForInPort: (Port*)aPort; +/* For getting the root object of a connection or port */ + ++ setRootObject: anObj forInPort: (Port*)aPort; +- setRootObject: anObj; +/* Used for setting the root object of a connection that we + created without one, or changing the root object of a connection + that already has one. */ + +- (int) outTimeout; +- (int) inTimeout; +- setOutTimeout: (int)to; +- setInTimeout: (int)to; +- portClass; +- setPortClass: aPortClass; +- proxyClass; +- coderClass; +- (Port*) outPort; +- (Port*) inPort; +- delegate; +- setDelegate: anObj; +/* Querying and setting some instance variables */ + +- (Proxy*) proxyForTarget: (unsigned)target; +- addProxy: (Proxy*)aProxy; +- (BOOL) includesProxyForTarget: (unsigned)target; +- removeProxy: (Proxy*)aProxy; +- (id ) localObjects; +- addLocalObject: anObj; +- (BOOL) includesLocalObject: anObj; +- removeLocalObject: anObj; +- (retval_t) connectionForward: (Proxy*)object : (SEL)sel : (arglist_t)frame; +- (const char *) _typeForSelector: (SEL)sel remoteTarget: (unsigned)target; +- (Dictionary*) _incomingConstPtrs; +- (Dictionary*) _outgoingConstPtrs; +/* Only subclassers and power-users need worry about these */ + +@end + +@protocol ConnectedCoding ++ (void) encodeObject: anObj withConnectedCoder: aRmc; +@end + +@interface Object (ConnectionDelegate) +- (Connection*) connection: ancestorConn didConnect: newConn; +/* If the delegate responds to this method, it will be used to ask the + delegate's permission to establish a new connection from the old one. + Often this is used so that the delegate can register for invalidation + notification on new child connections. + Normally return newConn. */ +@end + +#if 0 /* Put in Coder.m until ObjC runtime category-loading bug is fixed */ + +@interface Object (ConnectionRequests) +- classForConnectedCoder: aRmc; +/* Must return the class that will be created on the remote side + of the connection. + Used by the remote objects system to determine how the receiver + should be encoded across the network. + In general, you can: + return [Proxy class] to send a proxy of the receiver; + return [self class] to send the receiver bycopy. + The Object class implementation returns [Proxy class]. */ ++ (void) encodeObject: anObject withConnectedCoder: aRmc; +/* This message is sent to the class returned by -classForConnectedCoder: + The Proxy class implementation encodes a proxy for anObject. + The Object class implementation encodes the receiver itself. */ +@end + +@interface Object (Retaining) +/* Make sure objects don't crash when you send them messages. + These implementations, however, do nothing. */ +@end + +#endif /* 0 Put in Coder.m */ + +#define CONNECTION_DEFAULT_TIMEOUT 15000 /* in milliseconds */ + +#endif /* __Connection_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/DelegatePool.h b/Source/objects/DelegatePool.h new file mode 100644 index 000000000..bc6be226f --- /dev/null +++ b/Source/objects/DelegatePool.h @@ -0,0 +1,68 @@ +/* Interface for Objective-C "collection of delegates" object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Using this object, a delegator can have an arbitrary number of + delegates. Send a message to this object and the message will get + forwarded to the delegates on the list. */ + +#ifndef __DelegatePool_h_OBJECTS_INCLUDE +#define __DelegatePool_h_OBJECTS_INCLUDE + +#include +#include + +/* Available sending behaviors */ +enum DelegatePoolSendBehavior {SEND_TO_ALL = 0, + SEND_TO_FIRST_RESPONDER, + SEND_UNTIL_YES, + SEND_UNTIL_NO}; + +@interface DelegatePool +{ + struct objc_class *isa; + @public + unsigned char _send_behavior; + Array *_list; +} + +// CREATING AND FREEING; ++ alloc; ++ new; +- init; +- free; + +// MANIPULATING COLLECTION OF DELEGATES; +- delegatePoolAddObject: anObject; +- delegatePoolAddObjectIfAbsent: anObject; +- delegatePoolRemoveObject: anObject; +- (BOOL) delegatePoolIncludesObject: anObject; +- delegatePoolCollection; +- (unsigned char) delegatePoolSendBehavior; +- delegatePoolSetSendBehavior: (unsigned char)b; + +// FOR PASSING ALL OTHER MESSAGES TO DELEGATES; +- forward:(SEL)aSel :(arglist_t)argFrame; + +@end + +#endif /* __DelegatePool_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Dictionary.h b/Source/objects/Dictionary.h new file mode 100644 index 000000000..fc28dda41 --- /dev/null +++ b/Source/objects/Dictionary.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C Dictionary collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Dictionary_h_INCLUDE_GNU +#define __Dictionary_h_INCLUDE_GNU + +#include +#include + +@interface Dictionary : KeyedCollection +{ + coll_cache_ptr _contents_hash; // a hashtable to hold the contents; + int (*_comparison_function)(elt,elt); +} + + +@end + +#endif /* __Dictionary_h_INCLUDE_GNU */ + diff --git a/Source/objects/EltNode-h b/Source/objects/EltNode-h new file mode 100644 index 000000000..ce2cdb695 --- /dev/null +++ b/Source/objects/EltNode-h @@ -0,0 +1,41 @@ +/* Code for interface of Objective-C EltNode objects + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 + + This file is part of the GNU Objective-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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file gets included in all the ...EltNode.h files + Doing this silly #include stuff is a poor substitute for multiple + inheritance. sigh. + + Pattern: + + @interface FooEltNode : FooNode + #include + @end +*/ + + + +{ + elt _element; + int (*_elt_comparison_function)(elt,elt); +} +- (int(*)(elt,elt)) comparisonFunction; diff --git a/Source/objects/EltNode-m b/Source/objects/EltNode-m new file mode 100644 index 000000000..69df85904 --- /dev/null +++ b/Source/objects/EltNode-m @@ -0,0 +1,134 @@ +/* Code for implementation for Objective-C EltNode objects + Copyright (C) 1993 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 + + This file is part of the GNU Objective-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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file gets included in all the ...EltNode.m files. + Doing this silly #include stuff is a poor substitute for multiple + inheritance. sigh. + + Pattern: + + @implementation FooEltNode : FooNode + #include + @end +*/ + +#include + +- initElement: (elt)anElement + encoding: (const char *)eltEncoding +{ + [super init]; + _element = anElement; + _elt_comparison_function = elt_get_comparison_function(eltEncoding); + return self; +} + +/* Archiving must mimic the above designated initializer */ + +- (void) encodeWithCoder: (Coder*)aCoder +{ + const char *encoding; + + [super encodeWithCoder:aCoder]; + encoding = elt_get_encoding(_elt_comparison_function); + [aCoder encodeValueOfType:@encode(char*) at:&encoding + withName:"EltNode Content Type Encoding"]; + [aCoder encodeValueOfType:encoding + at:elt_get_ptr_to_member(encoding, &_element) + withName:"EltNode Content Element"]; +} + +- (elt*) _elementDataPtr +{ + return &_element; +} + +- (int(**)(elt,elt)) _eltComparisonFunctionPtr +{ + return &_elt_comparison_function; +} + ++ newWithCoder: (Coder*)aCoder +{ + id n; + char *encoding; + + n = [super newWithCoder:aCoder]; + [aCoder decodeValueOfType:@encode(char*) + at:&encoding + withName:NULL]; + *[n _eltComparisonFunctionPtr] = elt_get_comparison_function(encoding); + [aCoder decodeValueOfType:encoding + at:[n _elementDataPtr] + withName:NULL]; + return n; +} + +- write: (TypedStream*)aStream +{ + const char *encoding; + + [super write:aStream]; + encoding = elt_get_encoding(_elt_comparison_function); + objc_write_type(aStream, @encode(char*), &encoding); + objc_write_types(aStream, encoding, + elt_get_ptr_to_member(encoding, &_element)); + return self; +} + +- read: (TypedStream*)aStream +{ + char *encoding; + + [super read:aStream]; + objc_read_type(aStream, @encode(char*), &encoding); + _elt_comparison_function = elt_get_comparison_function(encoding); + objc_read_type(aStream, encoding, + elt_get_ptr_to_member(encoding,&_element)); + return self; +} + +- (int(*)(elt,elt)) comparisonFunction +{ + return _elt_comparison_function; +} + +- (elt) elementData +{ + return _element; +} + +- (int) compare: anotherObject +{ + /* perhaps we should do more checking first */ + return _elt_comparison_function(_element, [anotherObject elementData]); +} + +- printForDebugger +{ + elt_fprintf_elt(stdout, + elt_get_encoding(_elt_comparison_function), + _element); + printf("\n"); + return self; +} diff --git a/Source/objects/EltNodeCollector.h b/Source/objects/EltNodeCollector.h new file mode 100644 index 000000000..4f850574a --- /dev/null +++ b/Source/objects/EltNodeCollector.h @@ -0,0 +1,67 @@ +/* Interface for Objective-C EltNodeCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* EltNodeCollector */ + +#ifndef __EltNodeCollector_h_INCLUDE_GNU +#define __EltNodeCollector_h_INCLUDE_GNU + +#include +#include + +/* Protocol for a node that also holds an element */ +@protocol EltHolding +- initElement: (elt)anElement + encoding: (const char *)eltEncoding; +- (elt) elementData; +@end + + +/* It's is a bit unfortunate that we insist that the underlying + collector conform to IndexedCollecting. */ + +@interface EltNodeCollector : IndexedCollection +{ + @private + id _contents_collector; + id _node_class; + int (*_comparison_function)(elt,elt); +} + + +- initWithType: (const char *)contentEncoding + nodeCollector: aNodeCollector + nodeClass: aNodeClass; + +// The class of the autocreated link objects, must conform to ; +- eltNodeClass; + +// Getting the underlying node collector that holds the contents; +- contentsCollector; + +// Finding the node that contains anElement; +- (id ) eltNodeWithElement: (elt)anElement; + +@end + +#endif /* __EltNodeCollector_h_INCLUDE_GNU */ diff --git a/Source/objects/GapArray.h b/Source/objects/GapArray.h new file mode 100644 index 000000000..e39f89cde --- /dev/null +++ b/Source/objects/GapArray.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C GapArray collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __GapArray_h_INCLUDE_GNU +#define __GapArray_h_INCLUDE_GNU + +#include +#include + +@interface GapArray : Array +{ + @public + unsigned _gap_start; /* start of gap */ + unsigned _gap_size; /* size of gap */ +} + +@end + +#endif /* __GapArray_h_INCLUDE_GNU */ diff --git a/Source/objects/GapArrayPrivate.h b/Source/objects/GapArrayPrivate.h new file mode 100644 index 000000000..00d8c6a32 --- /dev/null +++ b/Source/objects/GapArrayPrivate.h @@ -0,0 +1,89 @@ +/* GapArray definitions for the use of subclass implementations + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + Copyright (C) 1993,1994 Kresten Krab Thorup + Dept. of Mathematics and Computer Science, Aalborg U., Denmark + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __GapArrayPrivate_h_INCLUDE_GNU +#define __GapArrayPrivate_h_INCLUDE_GNU + +#include +#include +#include + +#define GAP_TO_BASIC(INDEX) \ + ({ unsigned int __idx = (INDEX); \ + __idx >= self->_gap_start \ + ? __idx+self->_gap_size : __idx; }) + +#define BASIC_TO_GAP(INDEX) \ + ({ unsigned int __idx = (INDEX); \ + __idx < self->_gap_start \ + ? __idx : __idx-self->_gap_size; }) + +static inline void +gapMoveGapTo (GapArray* self, unsigned index) +{ + int i; + assert (index <= self->_capacity); + if (index < self->_gap_start) + { +#ifndef STABLE_MEMCPY + int b = index + self->_gap_size; + for (i = self->_gap_start + self->_gap_size - 1; i >= b; i--) + self->_contents_array[i] = self->_contents_array[i - self->_gap_size]; +#else + memcpy (self->_contents_array + index + self->_gap_size, + self->_contents_array + index, + self->_gap_start - index) +#endif + } + else + { +#ifndef STABLE_MEMCPY + for(i = self->_gap_start; i != index; i++) + self->_contents_array[i] = self->_contents_array[i - self->_gap_size]; +#else + memcpy (self->_contents_array + self->_gap_start, + self->_contents_array + self->_gap_start + self->_gap_size, + index - self->_gap_start); +#endif + } + self->_gap_start = index; +} + +static inline void +gapMakeHoleAt(GapArray *self, unsigned index) +{ + gapMoveGapTo (self, index); + self->_gap_start += 1; + self->_gap_size -= 1; +} + +static inline void +gapFillHoleAt(GapArray *self, unsigned index) +{ + gapMoveGapTo (self, index); + self->_gap_size += 1; +} + +#endif /* __GapArrayPrivate_h_INCLUDE_GNU */ diff --git a/Source/objects/Heap.h b/Source/objects/Heap.h new file mode 100644 index 000000000..d3592c4e3 --- /dev/null +++ b/Source/objects/Heap.h @@ -0,0 +1,42 @@ +/* Interface for Objective-C Heap collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Heap_h_INCLUDE_GNU +#define __Heap_h_INCLUDE_GNU + +#include +#include + +@interface Heap : Array +{ +} + +- addElement: (elt)anElement; +- (elt) removeFirstElement; + +- heapifyFromIndex: (unsigned)index; +- heapify; + +@end + +#endif /* __Heap_h_INCLUDE_GNU */ diff --git a/Source/objects/IndexedCollecting.h b/Source/objects/IndexedCollecting.h new file mode 100644 index 000000000..d8cb82331 --- /dev/null +++ b/Source/objects/IndexedCollecting.h @@ -0,0 +1,203 @@ +/* Protocol for Objective-C objects that hold elements accessible by index + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol inherits from the + protocol. + + The protocol defines the interface to a + collection of elements that are accessible by a key that is an index, + where the indeces in a collection are a contiguous series of unsigned + integers beginning at 0. This is the root of the protocol heirarchy + for all collections that hold their elements in some order. Elements + may be accessed, inserted, replaced and removed by their index. +*/ + +#ifndef __IndexedCollecting_h_OBJECTS_INCLUDE +#define __IndexedCollecting_h_OBJECTS_INCLUDE + +#include +#include + +typedef struct _IndexRange { + unsigned start; + unsigned end; +} IndexRange; +/* Includes elements from start to end-1 Is this ugly? + I do this so I can specify a NULL range + How about this instead: + typedef struct _IndexRange { + unsigned start; + unsigned length; + } +*/ + +//#define MakeIndexRange(START,END) \ +// ({ IndexRange __ir = {(START), (END)}; __ir; }) +// USE: ((IndexRange) {(START),(END)}) + +#define IndexRangeInside(RANGE1,RANGE2) \ + ({IndexRange __a=(RANGE1), __b=(RANGE2); \ + __a.start<=__b.start && __a.end>=__b.end;}) + + +@protocol IndexedCollecting + +// ADDING; +- insertObject: newObject atIndex: (unsigned)index; +- insertObject: newObject before: oldObject; +- insertObject: newObject after: oldObject; +- insertContentsOf: (id )aCollection atIndex: (unsigned)index; +- appendObject: newObject; +- prependObject: newObject; +- appendContentsOf: (id )aCollection; +- prependContentsOf: (id )aCollection; + +// REPLACING AND SWAPPING +- replaceObjectAtIndex: (unsigned)index with: newObject; +- replaceRange: (IndexRange)aRange with: (id )aCollection; +- replaceRange: (IndexRange)aRange using: (id )aCollection; +- swapAtIndeces: (unsigned)index1 : (unsigned)index2; + +// REMOVING +- removeObjectAtIndex: (unsigned)index; +- removeFirstObject; +- removeLastObject; +- removeRange: (IndexRange)aRange; + +// GETTING MEMBERS BY INDEX; +- objectAtIndex: (unsigned)index; +- firstObject; +- lastObject; + +// GETTING MEMBERS BY NEIGHBOR; +- successorOfObject: anObject; +- predecessorOfObject: anObject; + +// GETTING INDICES BY MEMBER; +- (unsigned) indexOfObject: anObject; +- (unsigned) indexOfObject: anObject + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange; +- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; + +// TESTING; +- (BOOL) includesIndex: (unsigned)index; +- (BOOL) contentsEqualInOrder: (id )aColl; +- (unsigned) indexOfFirstDifference: (id )aColl; +- (unsigned) indexOfFirstIn: (id )aColl; +- (unsigned) indexOfFirstNotIn: (id )aColl; + +// ENUMERATING; +- (BOOL) getPrevObject: (id*)anIdPtr withEnumState: (void**)enumState; +- withObjectsInRange: (IndexRange)aRange call:(void(*)(id))aFunc; +- withObjectsInReverseCall: (void(*)(id))aFunc; +- withObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithObjectsInReverseCall: (void(*)(id))aFunc; +- safeWithObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag; + +// SORTING; +- sortContents; +- sortObjectsByCalling: (int(*)(id,id))aFunc; +- sortAddObject: newObject; +- sortAddObject: newObject byCalling: (int(*)(id,id))aFunc; + + +// NON-OBJECT MESSAGE NAMES; + +// ADDING; +- appendElement: (elt)newElement; +- prependElement: (elt)newElement; +- insertElement: (elt)newElement atIndex: (unsigned)index; +- insertElement: (elt)newElement before: (elt)oldElement; +- insertElement: (elt)newElement after: (elt)oldElement; + +// REMOVING AND REPLACING; +- (elt) removeElementAtIndex: (unsigned)index; +- (elt) removeFirstElement; +- (elt) removeLastElement; +- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement; + +// GETTING ELEMENTS BY INDEX; +- (elt) elementAtIndex: (unsigned)index; +- (elt) firstElement; +- (elt) lastElement; + +// GETTING MEMBERS BY NEIGHBOR; +- (elt) successorOfElement: (elt)anElement; +- (elt) predecessorOfElement: (elt)anElement; + +// GETTING INDICES BY MEMBER; +- (unsigned) indexOfElement: (elt)anElement; +- (unsigned) indexOfElement: (elt)anElement + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange; +- (unsigned) indexOfElement: (elt)anElement inRange: (IndexRange)aRange + ifAbsentCall: (unsigned(*)(arglist_t))excFunc; + +// ENUMERATING; +- (BOOL) getPrevElement:(elt*)anElementPtr withEnumState: (void**)enumState; +- withElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc; +- withElementsInReverseCall: (void(*)(elt))aFunc; +- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithElementsInRange: (IndexRange)aRange call:(void(*)(elt))aFunc; +- safeWithElementsInReverseCall: (void(*)(elt))aFunc; +- safeWithElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag; + +// SORTING; +- sortElementsByCalling: (int(*)(elt,elt))aFunc; +- sortAddElement: (elt)newElement; +- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc; + +@end + +/* Most methods in the KeyedCollecting protocol that mention a key are + duplicated in the IndexedCollecting protocol, with their names + modified to reflect that the "key" now must be an unsigned integer, + (an "index"). The programmer should be able to use either of the + corresponding method names to the same effect. + + The new methods are provided in the IndexedCollecting protocol for: + 1) Better type checking for when an unsigned int is required. + 2) More intuitive method names. + + IndexedCollecting KeyedCollecting + ---------------------------------------------------------------------- + insertObject:atIndex insertObject:atKey: + replaceObjectAtIndex:with: replaceObjectAtKey:with: + removeObjectAtIndex: removeObjectAtKey: + objectAtIndex: objectAtKey: + includesIndex: includesKey: + + insertElement:atIndex insertElement:atKey: + replaceElementAtIndex:with: replaceElementAtKey:with: + removeElementAtIndex: removeElementAtKey: + elementAtIndex: elementAtKey: + +*/ + +#endif /* __IndexedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/IndexedCollection.h b/Source/objects/IndexedCollection.h new file mode 100644 index 000000000..3e7a4f758 --- /dev/null +++ b/Source/objects/IndexedCollection.h @@ -0,0 +1,66 @@ +/* Interface for Objective-C Sequential Collection object. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IndexedCollection_h_INCLUDE_GNU +#define __IndexedCollection_h_INCLUDE_GNU + +#include +#include +#include + +@interface IndexedCollection : KeyedCollection + +@end + +/* The only subclassResponsibilities in IndexedCollection are: + + insertElement:atIndex: + removeElementAtIndex: + elementAtIndex: + + but subclass will want to override others as well in order to + increase efficiency. The following are especially important if + the subclass's implementation of "elementAtIndex:" is not efficient: + + replaceElementAtIndex:with: + swapAtIndeces:: + shallowCopyReplaceFrom:to:with: + sortAddElement:byCalling: + removeElement: + firstElement + lastElement + shallowCopyFrom:to: + withElementsCall:whileTrue: + withElementsInReverseCall:whileTrue: + + and perhaps: + + appendElement: + prependElement: + indexOfElement: + withElementsInReverseCall: + +*/ + + +#endif /* __IndexedCollection_h_INCLUDE_GNU */ diff --git a/Source/objects/IndexedCollectionPrivate.h b/Source/objects/IndexedCollectionPrivate.h new file mode 100644 index 000000000..02bf8044a --- /dev/null +++ b/Source/objects/IndexedCollectionPrivate.h @@ -0,0 +1,47 @@ +/* IndexedCollection definitions for the use of subclass implementations only + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IndexedCollectionPrivate_h_INCLUDE_GNU +#define __IndexedCollectionPrivate_h_INCLUDE_GNU + +#include +#include + +/* To be used inside a method for making sure that index + is not above range. +*/ +#define CHECK_INDEX_RANGE_ERROR(INDEX, OVER) \ +({if (INDEX >= OVER) \ + [self error:"in %s, index out of range", sel_get_name(_cmd)];}) + + +/* For use with subclasses of IndexedCollections that allow elements to + be added, but not added at particular indices---the collection itself + determines the order. +*/ +#define INSERTION_ERROR() \ +([self error:"in %s, this collection does not allow insertions", \ + sel_get_name(aSel)];) + + +#endif /* __IndexedCollectionPrivate_h_INCLUDE_GNU */ diff --git a/Source/objects/InvalidationListening.h b/Source/objects/InvalidationListening.h new file mode 100644 index 000000000..3748381db --- /dev/null +++ b/Source/objects/InvalidationListening.h @@ -0,0 +1,37 @@ +/* Protocol for GNU Objective-C objects that understand an invalidation msg + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __InvalidationListening_h_OBJECTS_INCLUDE +#define __InvalidationListening_h_OBJECTS_INCLUDE + +/* This protocol is just temporary. It will disappear when GNU writes + a more general notification system. + It is not recommended that you use it in your code. */ + +@protocol InvalidationListening + +- senderIsInvalid: sender; + +@end + +#endif /* __InvalidationListening_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/KeyedCollecting.h b/Source/objects/KeyedCollecting.h new file mode 100644 index 000000000..8f3335986 --- /dev/null +++ b/Source/objects/KeyedCollecting.h @@ -0,0 +1,116 @@ +/* Protocol for Objective-C objects holding (keyElement,contentElement) pairs. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* The protocol inherits from the protocol. + + The protocol defines the interface to a + collection of elements that are accessible by a key, where the key is + some unique element. Pairs of (key element, content element) may be + added, removed and replaced. The keys and contents may be tested, + enumerated and copied. +*/ + +#ifndef __KeyedCollecting_h_OBJECTS_INCLUDE +#define __KeyedCollecting_h_OBJECTS_INCLUDE + +#include +#include + +@protocol KeyedCollecting + +// ADDING; +- putObject: newContentObject atKey: (elt)aKey; + +// REPLACING AND SWAPPING; +- replaceObjectAtKey: (elt)aKey with: newContentObject; +- swapAtKeys: (elt)key1 : (elt)key2; + +// REMOVING; +- removeObjectAtKey: (elt)aKey; + +// GETTING ELEMENTS AND KEYS; +- objectAtKey: (elt)aKey; +- keyObjectOfObject: aContentObject; + +// TESTING; +- (BOOL) includesKey: (elt)aKey; + +// ENUMERATIONS; +- withKeyObjectsCall: (void(*)(id))aFunc; +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc; +- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithKeyObjectsCall: (void(*)(id))aFunc; +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc; +- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc + whileTrue: (BOOL *)flag; + + +// NON-OBJECT ELEMENT METHOD NAMES; + +// INITIALIZING; +- initWithType: (const char *)contentsEncoding + keyType: (const char *)keyEncoding; +- initKeyType: (const char *)keyEncoding; + +// ADDING; +- putElement: (elt)newContentElement atKey: (elt)aKey; + +// REPLACING; +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement; +- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// REMOVING; +- (elt) removeElementAtKey: (elt)aKey; +- (elt) removeElementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// GETTING ELEMENTS AND KEYS; +- (elt) elementAtKey: (elt)aKey; +- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc; +- (elt) keyElementOfElement: (elt)aContentObject; +- (elt) keyElementOfElement: (elt)aContentObject + ifAbsentCall: (elt(*)(arglist_t))excFunc; + +// TESTING; +- (const char *) keyType; + +// ENUMERATING; +- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr + withEnumState: (void**)enumState; +- withKeyElementsCall: (void(*)(elt))aFunc; +- withKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc; +- withKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc + whileTrue: (BOOL *)flag; + +// ENUMERATING WHILE CHANGING CONTENTS; +- safeWithKeyElementsCall: (void(*)(elt))aFunc; +- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc; +- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc + whileTrue: (BOOL *)flag; + +@end + +#endif /* __KeyedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/KeyedCollection.h b/Source/objects/KeyedCollection.h new file mode 100644 index 000000000..2e77dd700 --- /dev/null +++ b/Source/objects/KeyedCollection.h @@ -0,0 +1,45 @@ +/* Interface for Objective-C KeyedCollection collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __KeyedCollection_h_INCLUDE_GNU +#define __KeyedCollection_h_INCLUDE_GNU + +#include +#include +#include + +@interface KeyedCollection : Collection + +@end + +/* The only subclassResponsibilities in IndexedCollection are: + + keyDescription + insertElement:atKey: + removeElementAtKey: + elementAtKey: + includesKey: + getNextKey:content:withEnumState: +*/ + +#endif /* __KeyedCollection_h_INCLUDE_GNU */ diff --git a/Source/objects/LinkedList.h b/Source/objects/LinkedList.h new file mode 100644 index 000000000..b6a2f7e20 --- /dev/null +++ b/Source/objects/LinkedList.h @@ -0,0 +1,48 @@ +/* Interface for Objective-C LinkedList collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedList_h_INCLUDE_GNU +#define __LinkedList_h_INCLUDE_GNU + +#include +#include + +/* The protocol defines the interface to an object + that may be an element in a LinkedList. +*/ +@protocol LinkedListComprising +- nextLink; +- prevLink; +- setNextLink: (id )aLink; +- setPrevLink: (id )aLink; +@end + +@interface LinkedList : IndexedCollection +{ + id _first_link; + unsigned int _count; +} + +@end + +#endif /* __LinkedList_h_INCLUDE_GNU */ diff --git a/Source/objects/LinkedListEltNode.h b/Source/objects/LinkedListEltNode.h new file mode 100644 index 000000000..d2d0a153e --- /dev/null +++ b/Source/objects/LinkedListEltNode.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C LinkedListEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedListEltNode_h_INCLUDE_GNU +#define __LinkedListEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface LinkedListEltNode : LinkedListNode +#include +@end + +#endif /* __LinkedListEltNode_h_INCLUDE_GNU */ diff --git a/Source/objects/LinkedListNode.h b/Source/objects/LinkedListNode.h new file mode 100644 index 000000000..c09229e5b --- /dev/null +++ b/Source/objects/LinkedListNode.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C LinkedListNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LinkedListNode_h_INCLUDE_GNU +#define __LinkedListNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface LinkedListNode : Object +{ + id _next; + id _prev; +} +@end + +#endif /* __LinkedListNode_h_INCLUDE_GNU */ + diff --git a/Source/objects/Lock.h b/Source/objects/Lock.h new file mode 100644 index 000000000..7a3cd2b92 --- /dev/null +++ b/Source/objects/Lock.h @@ -0,0 +1,35 @@ +/* Interface for GNU Objective-C mutex lock + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Lock_h_OBJECTS_INCLUDE +#define __Lock_h_OBJECTS_INCLUDE + +#include +#include + +@interface Lock : Object +{ +} +@end + +#endif /* __Lock_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Locking.h b/Source/objects/Locking.h new file mode 100644 index 000000000..4dfab0714 --- /dev/null +++ b/Source/objects/Locking.h @@ -0,0 +1,35 @@ +/* Protocol for GNU Objective-C mutex locks + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Locking_h_INCLUDE_GNU +#define __Locking_h_INCLUDE_GNU + +#include +#include + +@protocol Locking +- (void) lock; +- (void) unlock; +@end + +#endif /* __Locking_h_INCLUDE_GNU */ diff --git a/Source/objects/Magnitude.h b/Source/objects/Magnitude.h new file mode 100644 index 000000000..821ee42be --- /dev/null +++ b/Source/objects/Magnitude.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C Magnitude object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Magnitude_h_INCLUDE_GNU +#define __Magnitude_h_INCLUDE_GNU + +#include +#include +#include + +@interface Magnitude : Object + +@end + +#endif /* __Magnitude_h_INCLUDE_GNU */ diff --git a/Source/objects/MappedCollector.h b/Source/objects/MappedCollector.h new file mode 100644 index 000000000..6856d6eb3 --- /dev/null +++ b/Source/objects/MappedCollector.h @@ -0,0 +1,41 @@ +/* Interface for Objective-C MappedCollector collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MappedCollector_h_INCLUDE_GNU +#define __MappedCollector_h_INCLUDE_GNU + +#include +#include + +@interface MappedCollector : KeyedCollection +{ + id _map; + id _domain; +} + +- initCollection: (id )aDomain + map: (id )aMap; + +@end + +#endif /* __MappedCollector_h_INCLUDE_GNU */ diff --git a/Source/objects/MemoryStream.h b/Source/objects/MemoryStream.h new file mode 100644 index 000000000..3f057414b --- /dev/null +++ b/Source/objects/MemoryStream.h @@ -0,0 +1,55 @@ +/* Interface for GNU Objective C memory stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MemoryStream_h_OBJECTS_INCLUDE +#define __MemoryStream_h_OBJECTS_INCLUDE + +#include +#include + +@interface MemoryStream : Stream +{ + int type; + char *buffer; + int size; + int eofPosition; + int prefix; + int position; +} + +- initWithSize: (unsigned)s; +- (char *) streamBuffer; +- (unsigned) streamBufferLength; +- (unsigned) streamPrefix; +- (unsigned) streamEofPosition; +- (void) setStreamBufferSize: (unsigned)s; + +/* xxx This interface will change */ +- _initOnMallocBuffer: (char*)b + size: (unsigned)s /* size of malloc'ed buffer */ + eofPosition: (unsigned)l /* length of buffer with data for reading */ + prefix: (unsigned)p /* reset for this position */ + position: (unsigned)i; /* current position for reading/writing */ +@end + +#endif /* __MemoryStream_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Ordering.h b/Source/objects/Ordering.h new file mode 100644 index 000000000..ed34bf333 --- /dev/null +++ b/Source/objects/Ordering.h @@ -0,0 +1,47 @@ +/* Protocol for Objective-C objects that can be ordered. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Ordering_h_INCLUDE_GNU +#define __Ordering_h_INCLUDE_GNU + +#include +#include + +@protocol Ordering + +- (int) compare: anObject; + +- (BOOL) greaterThan: anObject; +- (BOOL) greaterThanOrEqual: anObject; + +- (BOOL) lessThan: anObject; +- (BOOL) lessThanOrEqual: anObject; + +- (BOOL) between: firstObject and: secondObject; + +- maximum: anObject; +- minimum: anObject; + +@end + +#endif /* __Ordering_h_INCLUDE_GNU */ diff --git a/Source/objects/Port.h b/Source/objects/Port.h new file mode 100644 index 000000000..48c948f6c --- /dev/null +++ b/Source/objects/Port.h @@ -0,0 +1,61 @@ +/* Interface for abstract superclass port for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Port_h_OBJECTS_INCLUDE +#define __Port_h_OBJECTS_INCLUDE + +#include +#include +#include + +@class Connection; + +@interface Port : RetainingNotifier + +/* xxx These will probably change */ ++ newRegisteredPortWithName: (const char *)n; ++ newPortFromRegisterWithName: (const char *)n onHost: (const char *)host; ++ newPort; + +/* xxx These sending and receiving interfaces will change */ + +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*) remote; +- (int) sendPacket: (const char *)b length: (int)l + toPort: (Port*)remote + timeout: (int) milliseconds; + +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote; +- (int) receivePacket: (char*)b length: (int)l + fromPort: (Port**) remote + timeout: (int) milliseconds; + +- (BOOL) isSoft; + +- (unsigned) hash; +- (BOOL) isEqual: anotherPort; + +@end + +#endif /* __Port_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Proxy.h b/Source/objects/Proxy.h new file mode 100644 index 000000000..768be4481 --- /dev/null +++ b/Source/objects/Proxy.h @@ -0,0 +1,82 @@ +/* Interface for GNU Objective-C proxy for remote objects messaging + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Proxy_h_OBJECTS_INCLUDE +#define __Proxy_h_OBJECTS_INCLUDE + +#include +#include +#include + +@class ConnectedCoder; + +@interface Proxy +{ +@public + struct objc_class *isa; + unsigned target; + Connection *connection; + unsigned retain_count; +#if NeXT_runtime + coll_cache_ptr _method_types; + Protocol *protocol; +#endif +} + +/* xxx Change name to newForTarget:connection: */ ++ newForRemote: (unsigned)target connection: (Connection*)c; + +- self; +#if NeXT_runtime ++ class; +#else ++ (Class*) class; +#endif + +- invalidateProxy; +- (BOOL) isProxy; +- (unsigned) targetForProxy; +- connectionForProxy; + +- forward: (SEL)aSel :(arglist_t)frame; + +- classForConnectedCoder: aRmc; ++ (void) encodeObject: anObject withConnectedCoder: aRmc; + ++ newWithCoder: aCoder; +- (void) encodeWithCoder: aCoder; + +/* Only needed with NeXT runtime. */ +- (const char *) selectorTypeForProxy: (SEL)selector; + +@end + +@interface Object (IsProxy) +- (BOOL) isProxy; +@end + +@interface Protocol (RemoteCoding) +- classForConnectedCoder: aRmc; +@end + +#endif /* __Proxy_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Queue.h b/Source/objects/Queue.h new file mode 100644 index 000000000..f845ef99b --- /dev/null +++ b/Source/objects/Queue.h @@ -0,0 +1,41 @@ +/* Interface for Objective-C Queue object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Queue_h_INCLUDE_GNU +#define __Queue_h_INCLUDE_GNU + +#include +#include + +@interface Queue : CircularArray + +- enqueueObject: newObject; +- dequeueObject; + +// NON-OBJECT MESSAGE NAMES; +- enqueueElement: (elt)newElement; +- (elt) dequeueElement; + +@end + +#endif /* __Queue_h_INCLUDE_GNU */ diff --git a/Source/objects/RBTree.h b/Source/objects/RBTree.h new file mode 100644 index 000000000..7725baaee --- /dev/null +++ b/Source/objects/RBTree.h @@ -0,0 +1,40 @@ +/* Interface for Objective-C Red-Black Tree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTree_h_INCLUDE_GNU +#define __RBTree_h_INCLUDE_GNU + +#include +#include + +@protocol RBTreeComprising +- (BOOL) isRed; +- setRed; +- setBlack; +@end + +@interface RBTree : BinaryTree + +@end + +#endif /* __RBTree_h_INCLUDE_GNU */ diff --git a/Source/objects/RBTreeEltNode.h b/Source/objects/RBTreeEltNode.h new file mode 100644 index 000000000..0606a6f71 --- /dev/null +++ b/Source/objects/RBTreeEltNode.h @@ -0,0 +1,35 @@ +/* Interface for Objective-C RBTreeEltNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTreeEltNode_h_INCLUDE_GNU +#define __RBTreeEltNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface RBTreeEltNode : RBTreeNode +#include +@end + +#endif /* __RBTreeEltNode_h_INCLUDE_GNU */ diff --git a/Source/objects/RBTreeNode.h b/Source/objects/RBTreeNode.h new file mode 100644 index 000000000..e2eb4d6d7 --- /dev/null +++ b/Source/objects/RBTreeNode.h @@ -0,0 +1,37 @@ +/* Interface for Objective-C RBTreeNode object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RBTreeNode_h_INCLUDE_GNU +#define __RBTreeNode_h_INCLUDE_GNU + +#include +#include +#include + +@interface RBTreeNode : BinaryTreeNode +{ + BOOL _red; +} +@end + +#endif /* __RBTreeNode_h_INCLUDE_GNU */ diff --git a/Source/objects/RNGAdditiveCongruential.h b/Source/objects/RNGAdditiveCongruential.h new file mode 100644 index 000000000..fd5d07e27 --- /dev/null +++ b/Source/objects/RNGAdditiveCongruential.h @@ -0,0 +1,44 @@ +/* Interface for additive congruential pseudo-random num generating + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Additive Congruential Method, + from Robert Sedgewick, "Algorithms" */ + +#ifndef __RNGAdditiveCongruential_h_INCLUDE_GNU +#define __RNGAdditiveCongruential_h_INCLUDE_GNU + +#include +#include + +@interface RNGAdditiveCongruential : Object +{ + long *table; + int table_size; + int tap1; + int tap2; + int index; +} + +@end + +#endif /* __RNGAdditiveCongruential_h_INCLUDE_GNU */ diff --git a/Source/objects/RNGBerkeley.h b/Source/objects/RNGBerkeley.h new file mode 100644 index 000000000..bfa67e24c --- /dev/null +++ b/Source/objects/RNGBerkeley.h @@ -0,0 +1,74 @@ +/* Interface for Berkeley random()-compatible generation for Objective-C + + Reworked by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RNGBerkeley_h_INCLUDE_GNU +#define __RNGBerkeley_h_INCLUDE_GNU + +/* + * Copyright (c) 1983 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * It was reworked for the GNU Objective-C Library by R. Andrew McCallum + */ + +#include +#include + +@interface RNGBerkeley : Object +{ + int foo[2]; + long int randtbl[32]; /* Size must match DEG_3 + 1 from RNGBerkeley.m */ + long int *fptr; + long int *rptr; + long int *state; + int rand_type; + int rand_deg; + int rand_sep; + long int *end_ptr; +} + +- (void) _srandom: (unsigned int)x; +- (void*) _initstateSeed: (unsigned int)seed + state: (void*)arg_state + size: (size_t)n; +- (void*) _setstate: (void*)arg_state; + +@end + +#endif /* __RNGBerkeley_h_INCLUDE_GNU */ diff --git a/Source/objects/Random.h b/Source/objects/Random.h new file mode 100644 index 000000000..c800c16a1 --- /dev/null +++ b/Source/objects/Random.h @@ -0,0 +1,69 @@ +/* Interface for Objective-C object providing randoms in uniform distribution + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Random_h_INCLUDE_GNU +#define __Random_h_INCLUDE_GNU + +#include +#include + +@interface Random : Object +{ + id rng; +} + ++ initialize; ++ (id ) defaultRandomGeneratorClass; ++ setDefaultRandomGeneratorClass: (id )aRNG; + ++ (float) chiSquareOfRandomGenerator: (id )aRNG + iterations: (int)n + range: (long)r; ++ (float) chiSquareOfRandomGenerator: (id )aRNG; + +- init; + +- setRandomSeedFromClock; +- setRandomSeed: (long)seed; + +- (long) randomInt; +- (long) randomIntBetween: (long)lowBound and: (long)highBound; +- (long) randomDie: (long)numSides; /* between 0 and numSides-1 */ + +- (BOOL) randomCoin; +- (BOOL) randomCoinWithProbability: (double)p; + +- (float) randomFloat; +- (float) randomFloatBetween: (float)lowBound and: (float)highBound; +- (float) randomFloatProbability; + +- (double) randomDouble; +- (double) randomDoubleBetween: (double)lowBound and: (double)highBound; +- (double) randomDoubleProbability; + +- read: (TypedStream*)aStream; +- write: (TypedStream*)aStream; + +@end + +#endif /* __Random_h_INCLUDE_GNU */ diff --git a/Source/objects/RandomGenerating.h b/Source/objects/RandomGenerating.h new file mode 100644 index 000000000..260282942 --- /dev/null +++ b/Source/objects/RandomGenerating.h @@ -0,0 +1,39 @@ +/* Protocol for Objective-C objects that generate random bits + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __RandomGenerating_h_INCLUDE_GNU +#define __RandomGenerating_h_INCLUDE_GNU + +#include + +@protocol RandomGenerating + ++ alloc; +- init; + +- (void) setRandomSeed: (long)seed; +- (long) nextRandom; + +@end + +#endif /* __RandomGenerating_h_INCLUDE_GNU */ diff --git a/Source/objects/Retaining.h b/Source/objects/Retaining.h new file mode 100644 index 000000000..70f1760e3 --- /dev/null +++ b/Source/objects/Retaining.h @@ -0,0 +1,38 @@ +/* Protocol for GNU Objective-C objects that can keep a retain count. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Retaining_h_OBJECTS_INCLUDE +#define __Retaining_h_OBJECTS_INCLUDE + +#include + +@protocol Retaining + +- retain; +- (oneway void) release; +- (void) dealloc; +- (unsigned) retainCount; + +@end + +#endif /* __Retaining_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/RetainingNotifier.h b/Source/objects/RetainingNotifier.h new file mode 100644 index 000000000..8cdc22bec --- /dev/null +++ b/Source/objects/RetainingNotifier.h @@ -0,0 +1,57 @@ +/* Interface for reference-counted invalidation notifer object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Reference Counted object with invalidation notification + This object is just temporary. Eventually, we should separate + reference counting functionality from notification functionality */ + +#ifndef __RetainingNotifier_h +#define __RetainingNotifier_h + +#include +#include +#include +#include +#include + +@interface RetainingNotifier : Object +{ + Lock *refGate; + List *notificationList; + BOOL isValid; + int retain_count; +} + ++ initialize; +- init; +- free; +- (unsigned) retainCount; +- registerForInvalidationNotification: (id )anObject; +- unregisterForInvalidationNotification: (id )anObject; +- (BOOL) isValid; +- invalidate; +- copy; + +@end + +#endif /* __RetainingNotifier_h */ diff --git a/Source/objects/Set.h b/Source/objects/Set.h new file mode 100644 index 000000000..5e7278cb0 --- /dev/null +++ b/Source/objects/Set.h @@ -0,0 +1,54 @@ +/* Interface for Objective-C Set collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Set_h_OBJECTS_INCLUDE +#define __Set_h_OBJECTS_INCLUDE + +#include +#include + +@interface Set : Collection +{ + coll_cache_ptr _contents_hash; // a hashtable to hold the contents; +} + +// MANAGING CAPACITY; ++ (unsigned) defaultCapacity; + +// INITIALIZING AND FREEING; +- initWithType: (const char *)contentEncoding + capacity: (unsigned)aCapacity; +- initWithCapacity: (unsigned)aCapacity; + +// SET OPERATIONS; +- intersectWithCollection: (id )aCollection; +- unionWithCollection: (id )aCollection; +- differenceWithCollection: (id )aCollection; + +- shallowCopyIntersectWithCollection: (id )aCollection; +- shallowCopyUnionWithCollection: (id )aCollection; +- shallowCopyDifferenceWithCollection: (id )aCollection; + +@end + +#endif /* __Set_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/SocketPort.h b/Source/objects/SocketPort.h new file mode 100644 index 000000000..19e90d464 --- /dev/null +++ b/Source/objects/SocketPort.h @@ -0,0 +1,57 @@ +/* Interface for socket-based port object for use with Connection + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SocketPort_h_INCLUDE_GNU +#define __SocketPort_h_INCLUDE_GNU + +#include +#include + +#include +#include +#include + +typedef struct sockaddr_in sockport_t; + +@interface SocketPort : Port +{ + sockport_t sockPort; + int sock; /* socket if local, 0 if remote */ + BOOL close_on_dealloc; +} + + ++ newForSockPort: (sockport_t)s close: (BOOL)f; ++ newForSockPort: (sockport_t)s; ++ newLocalWithNumber: (int)n; ++ newLocal; ++ newRemoteWithNumber: (int)n onHost: (const char*)h; + +- (sockport_t) sockPort; + +- (int) socket; +- (int) socketPortNumber; + +@end + +#endif /* __SocketPort_h_INCLUDE_GNU */ diff --git a/Source/objects/SplayTree.h b/Source/objects/SplayTree.h new file mode 100644 index 000000000..73e3edfcf --- /dev/null +++ b/Source/objects/SplayTree.h @@ -0,0 +1,48 @@ +/* Interface for Objective-C SplayTree collection object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Splay Tree. + Sleator and Tarjan. "Self-adjusting binary search trees." + Journal of the ACM, 32(3):652-686, 1985. + + includesObject:, minObject, maxObject, nextObject:, sortAddObject, + and removeObject: operations can all be done in O(lg n) amortized time. +*/ + + +#ifndef __SplayTree_h_INCLUDE_GNU +#define __SplayTree_h_INCLUDE_GNU + +#include +#include + +@interface SplayTree : BinaryTree +{ +} + +- splayNode: aNode; + +@end + +#endif /* __SplayTree_h_INCLUDE_GNU */ diff --git a/Source/objects/Stack.h b/Source/objects/Stack.h new file mode 100644 index 000000000..bfd7d5d02 --- /dev/null +++ b/Source/objects/Stack.h @@ -0,0 +1,47 @@ +/* Interface for Objective-C Stack object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __Stack_h_INCLUDE_GNU +#define __Stack_h_INCLUDE_GNU + +#include +#include + +@interface Stack : Array + +- pushObject: anObject; +- popObject; +- topObject; +- duplicateTop; +- exchangeTop; + +// NON-OBJECT MESSAGE NAMES; +- pushElement: (elt)anElement; +- (elt) popElement; +- (elt) topElement; + + +@end + +#endif /* __Stack_h_INCLUDE_GNU */ + diff --git a/Source/objects/StdioStream.h b/Source/objects/StdioStream.h new file mode 100644 index 000000000..79e22f662 --- /dev/null +++ b/Source/objects/StdioStream.h @@ -0,0 +1,50 @@ +/* Interface for GNU Objective C stdio stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __StdioStream_h__OBJECTS_INCLUDE +#define __StdioStream_h__OBJECTS_INCLUDE + +#include +#include +#include + +@interface StdioStream : Stream +{ + FILE *fp; +} + ++ standardIn; ++ standardOut; ++ standardError; + +- initWithFilePointer: (FILE*)afp fmode: (const char *)m; +- initWithFilename: (const char *)name fmode: (const char *)m; +- initWithFileDescriptor: (int)fd fmode: (const char *)m; + +- initWithPipeTo: (const char *)systemCommand; +- initWithPipeFrom: (const char *)systemCommand; + +@end + +#endif /* __StdioStream_h__OBJECTS_INCLUDE */ + diff --git a/Source/objects/Stream.h b/Source/objects/Stream.h new file mode 100644 index 000000000..590f777bf --- /dev/null +++ b/Source/objects/Stream.h @@ -0,0 +1,67 @@ +/* Interface for GNU Objective C byte stream + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __Stream_h__OBJECTS_INCLUDE +#define __Stream_h__OBJECTS_INCLUDE + +#include + +/* More modes needed? truncate? create? */ +enum +{ + STREAM_READONLY = 0, + STREAM_WRITEONLY, + STREAM_READWRITE +}; + +@interface Stream : Object +{ + int mode; +} + +- initWithMode: (int)m; +- init; + +- (int) writeByte: (unsigned char)b; +- (int) readByte: (unsigned char*)b; + +- (int) writeBytes: (const void*)b length: (int)l; +- (int) readBytes: (void*)b length: (int)l; + +- (int) writeFormat: (const char *)format, ...; +- (int) readFormat: (const char *)format, ...; + +- (void) writeLine: (const char *)l; +- (char *) readLine; + +- (void) rewindStream; +- (void) flushStream; +- (void) setStreamPosition: (unsigned)i; +- (unsigned) streamPosition; +- (BOOL) streamEof; +- (int) streamMode; + +@end + +#endif /* __Stream_h__OBJECTS_INCLUDE */ + diff --git a/Source/objects/TextCoder.h b/Source/objects/TextCoder.h new file mode 100644 index 000000000..0ae9f27e5 --- /dev/null +++ b/Source/objects/TextCoder.h @@ -0,0 +1,37 @@ +/* Interface for GNU Objective-C text coder object for use serializing + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: July 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TextCoder_h_OBJECTS_INCLUDE +#define __TextCoder_h_OBJECTS_INCLUDE + +#include +#include + +@interface TextCoder : Coder +{ + int indentation; +} + +@end + +#endif /* __TextCoder_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/Time.h b/Source/objects/Time.h new file mode 100644 index 000000000..496ef947f --- /dev/null +++ b/Source/objects/Time.h @@ -0,0 +1,85 @@ +/* Interface for Objective-C Time object + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This is a combination of Smalltalk's Time and Date objects */ + +#ifndef __Time_h_OBJECTS_INCLUDE +#define __Time_h_OBJECTS_INCLUDE + +#include +#include +#include +#include + +@interface Time : Magnitude +{ + struct timeval tv; /* seconds and useconds */ + struct timezone tz; /* minutes from Greenwich, and correction */ +} + +/* Change these names? */ ++ (long) secondClockValue; ++ getClockValueSeconds: (long *)sec microseconds: (long *)usec; + ++ (long) millisecondsToRun: (void(*)())aFunc; ++ getSeconds: (long *)sec microseconds: (long *)usec toRun: (void(*)())aFunc; + ++ (unsigned) indexOfDayName: (const char *)dayName; ++ (const char *) nameOfDayIndex: (unsigned)dayIndex; ++ (unsigned) indexOfMonthName: (const char *)monthName; ++ (const char *) nameOfMonthIndex: (unsigned)monthIndex; ++ (unsigned) daysInMonthIndex: (unsigned)monthIndex forYear: (unsigned)year; ++ (unsigned) daysInYear: (unsigned)year; ++ (BOOL) leapYear: (unsigned)year; + +- initNow; +- initDayIndex: (unsigned)dayIndex + monthIndex: (unsigned)monthIndex + year: (unsigned)year; +- initSeconds: (long)numSeconds microseconds: (long)numMicroseconds; +- initSeconds: (long)numSeconds; + +- setSeconds: (long)numSeconds microseconds: (long)numMicroseconds; +- setSeconds: (long)numSeconds; + +- (long) days; +- (long) hours; +- (long) minutes; +- (long) seconds; +- (long) microseconds; + +- addTime: (Time*)aTimeObj; +- addDays: (unsigned)num; +- addHours: (unsigned)num; +- addMinutes: (unsigned)num; +- addSeconds: (unsigned)num; + +- subtractTime: (Time*)aTimeObj; +- subtractDays: (unsigned)num; +- subtractHours: (unsigned)num; +- subtractMinutes: (unsigned)num; +- subtractSeconds: (unsigned)num; + +@end + +#endif /* __Time_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/ValueHolding.h b/Source/objects/ValueHolding.h new file mode 100644 index 000000000..da14b32f8 --- /dev/null +++ b/Source/objects/ValueHolding.h @@ -0,0 +1,50 @@ +/* Protocol for Objective-C objects that hold numerical and/or string values. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ValueHolding_h_INCLUDE_GNU +#define __ValueHolding_h_INCLUDE_GNU + +#include + +@class String; + +@protocol ValueGetting +- (int) intValue; +- (float) floatValue; +- (double) doubleValue; +- (const char *) cStringValue; +- (String *) stringValue; +@end + +@protocol ValueSetting +- setIntValue: (int)anInt; +- setFloatValue: (float)aFloat; +- setDoubleValue: (double)aDouble; +- setCStringValue: (const char *)aCString; +- setStringValue: (String*)aString; +@end + +@protocol ValueHolding +@end + +#endif /* __ValueHolding_h_INCLUDE_GNU */ diff --git a/Source/objects/collhash.h b/Source/objects/collhash.h new file mode 100644 index 000000000..29245740e --- /dev/null +++ b/Source/objects/collhash.h @@ -0,0 +1,170 @@ +/* Hash tables for Objective C method dispatch, modified for libcoll. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + + +#ifndef __collhash_INCLUDE_GNU +#define __collhash_INCLUDE_GNU + +#ifdef IN_GCC +#include "gstddef.h" +#else +#include "stddef.h" +#endif + +#include + +/* This returns an unsigned int that is the closest power of two greater + than the argument. */ +/* If we can rely on having ffs() we could do this better */ +#define POWER_OF_TWO(n) \ +({ \ + unsigned _MASK = 1; \ + while (n > _MASK) \ + _MASK <<= 1; \ + _MASK; \ +}) + + +/* + * This data structure is used to hold items + * stored in a hash table. Each node holds + * a key/value pair. + * + * Items in the cache are really of type void *. + */ +typedef struct coll_cache_node +{ + struct coll_cache_node *next; /* Pointer to next entry on the list. + NULL indicates end of list. */ + elt key; /* Key used to locate the value. Used + to locate value when more than one + key computes the same hash + value. */ + elt value; /* Value stored for the key. */ +} *coll_node_ptr; + + +/* + * This data type is the function that computes a hash code given a key. + * Therefore, the key can be a pointer to anything and the function specific + * to the key type. + * + * Unfortunately there is a mutual data structure reference problem with this + * typedef. Therefore, to remove compiler warnings the functions passed to + * hash_new will have to be casted to this type. + */ +typedef unsigned int (*coll_hash_func_type)(elt); + +/* + * This data type is the function that compares two hash keys and returns an + * integer greater than, equal to, or less than 0, according as the first + * parameter is lexico-graphically greater than, equal to, or less than the + * second. + */ + +typedef int (*coll_compare_func_type)(elt, elt); + + +/* + * This data structure is the cache. + * + * It must be passed to all of the hashing routines + * (except for new). + */ +typedef struct coll_cache +{ + /* Variables used to implement the hash itself. */ + coll_node_ptr *node_table; /* Pointer to an array of hash nodes. */ + /* Variables used to track the size of the hash table so to determine + when to resize it. */ + unsigned int size; /* Number of buckets allocated for the hash table + (number of array entries allocated for + "node_table"). Must be a power of two. */ + unsigned int used; /* Current number of entries in the hash table. */ + unsigned int mask; /* Precomputed mask. */ + + /* Variables used to implement indexing through the hash table. */ + + /* commented out by mccallum */ + /* unsigned int last_bucket; Tracks which entry in the array where + the last value was returned. */ + /* Function used to compute a hash code given a key. + This function is specified when the hash table is created. */ + coll_hash_func_type hash_func; + /* Function used to compare two hash keys to see if they are equal. */ + coll_compare_func_type compare_func; +} *coll_cache_ptr; + + +/* Two important hash tables. */ +/* This should be removed +extern coll_cache_ptr module_hash_table, class_hash_table; +*/ + +/* Allocate and initialize a hash table. */ + +coll_cache_ptr coll_hash_new (unsigned int size, + coll_hash_func_type hash_func, + coll_compare_func_type compare_func); + +/* Deallocate all of the hash nodes and the cache itself. */ + +void coll_hash_delete (coll_cache_ptr cache); + +/* Deallocate all of the hash nodes. */ + +void coll_hash_empty (coll_cache_ptr cache); + +/* Add the key/value pair to the hash table. If the + hash table reaches a level of fullnes then it will be resized. + + assert if the key is already in the hash. */ + +void coll_hash_add (coll_cache_ptr *cachep, elt key, elt value); + +/* Remove the key/value pair from the hash table. + assert if the key isn't in the table. */ + +void coll_hash_remove (coll_cache_ptr cache, elt key); + +/* Used to index through the hash table. Start with NULL + to get the first entry. + + Successive calls pass the value returned previously. + ** Don't modify the hash during this operation *** + + Cache nodes are returned such that key or value can + be extracted. */ + +coll_node_ptr coll_hash_next (coll_cache_ptr cache, void** state); + +/* Used to return a value from a hash table using a given key. */ + +elt coll_hash_value_for_key (coll_cache_ptr cache, elt key); + + +extern coll_node_ptr coll_hash_node_for_key (coll_cache_ptr cache, elt key); + +#endif /* not __hash_INCLUDE_GNU */ diff --git a/Source/objects/config.h.in b/Source/objects/config.h.in new file mode 100644 index 000000000..3710728a1 --- /dev/null +++ b/Source/objects/config.h.in @@ -0,0 +1,30 @@ +/* Configuration information for the GNU Objective-C Library. + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: Oct 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __config_h_OBJECTS_INCLUDE +#define __config_h_OBJECTS_INCLUDE + +#define NeXT_runtime @NeXT_runtime@ +#define NeXT_cc @NeXT_cc@ + +#endif /* __config_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/elt.h b/Source/objects/elt.h new file mode 100644 index 000000000..cd2c8765b --- /dev/null +++ b/Source/objects/elt.h @@ -0,0 +1,56 @@ +/* Definition of elt union, a union of various primitive C types + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __elt_h_INCLUDE_GNU +#define __elt_h_INCLUDE_GNU + +#include + +/* Uncomment this #define to include double's if you really need them, + but on most architectures you'll be increasing sizeof(elt) by a + factor of two! */ + +/* #define ELT_INCLUDES_DOUBLE 1 */ +/* NOTE: This doesn't work yet. */ + +typedef union _elt +{ + id id_u; + SEL SEL_u; + int int_u; + unsigned int unsigned_int_u; + char char_u; + unsigned char unsigned_char_u; + short int short_int_u; + unsigned short int unsigned_short_int_u; + long int long_int_u; + unsigned long int unsigned_long_int_u; + float float_u; +#if (ELT_INCLUDES_DOUBLE) + double double_u; +#endif + const void *void_ptr_u; + char *char_ptr_u; /* change this to const char * */ +} elt; + +#endif /* __elt_h_INCLUDE_GNU */ diff --git a/Source/objects/eltfuncs.h b/Source/objects/eltfuncs.h new file mode 100644 index 000000000..d6d48d714 --- /dev/null +++ b/Source/objects/eltfuncs.h @@ -0,0 +1,85 @@ +/* Declarations of functions for dealing with elt unions + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __eltfuncs_h_INCLUDE_GNU +#define __eltfuncs_h_INCLUDE_GNU + +#include +#include +#include + +extern unsigned int elt_hash_int (elt key); +extern int elt_compare_ints (elt k1, elt k2); + +extern unsigned int elt_hash_unsigned_int (elt key); +extern int elt_compare_unsigned_ints (elt k1, elt k2); + +extern unsigned int elt_hash_long_int (elt key); +extern int elt_compare_long_ints (elt k1, elt k2); + +extern unsigned int elt_hash_unsigned_long_int (elt key); +extern int elt_compare_unsigned_long_ints (elt k1, elt k2); + +extern unsigned int elt_hash_char (elt key); +extern int elt_compare_chars (elt k1, elt k2); + +extern unsigned int elt_hash_unsigned_char (elt key); +extern int elt_compare_unsigned_chars (elt k1, elt k2); + +extern unsigned int elt_hash_short (elt key); +extern int elt_compare_shorts (elt k1, elt k2); + +extern unsigned int elt_hash_unsigned_short (elt key); +extern int elt_compare_unsigned_shorts (elt k1, elt k2); + +extern unsigned int elt_hash_float (elt key); +extern int elt_compare_floats (elt k1, elt k2); + +#if (ELT_INCLUDES_DOUBLE) +extern unsigned int elt_hash_double (elt key); +extern int elt_compare_doubles (elt k1, elt k2); +#endif + +extern int elt_compare_strings (elt k1, elt k2); +extern unsigned int elt_hash_string (elt key); + +extern int elt_compare_void_ptrs (elt k1, elt k2); +extern unsigned int elt_hash_void_ptr (elt key); + +extern unsigned int elt_hash_object (elt key); +extern int elt_compare_objects (elt k1, elt k2); + + +/* This returns a (int(*)(elt,elt)) */ +extern int (*(elt_get_comparison_function(const char *encoding)))(elt,elt); + +/* This returns a (unsigned int (*)(elt)) */ +extern unsigned int (*(elt_get_hash_function(const char *encoding)))(elt); + +extern const char *elt_get_encoding(int(*comparison_function)(elt,elt)); + +extern void *elt_get_ptr_to_member(const char *encoding, elt *anElement); + +extern void elt_fprintf_elt(FILE *fp, const char *encoding, elt anElement); + +#endif /* __eltfuncs_h_INCLUDE_GNU */ diff --git a/Source/objects/mframe.h b/Source/objects/mframe.h new file mode 100644 index 000000000..b08a2133e --- /dev/null +++ b/Source/objects/mframe.h @@ -0,0 +1,43 @@ +/* Interface for functions that dissect/make method calls + Copyright (C) 1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: Oct 1994 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __mframe_h_OBJECTS_INCLUDE +#define __mframe_h_OBJECTS_INCLUDE + +#include + +BOOL +dissect_method_call(arglist_t frame, const char *type, + void (*f)(int,void*,const char*,int)); + +retval_t +dissect_method_return(arglist_t frame, const char *type, + BOOL out_parameters, + void(*f)(int,void*,const char*,int)); + +void +make_method_call(const char *forward_type, + void(*fd)(int,void*,const char*), + void(*fe)(int,void*,const char*,int)); + +#endif /* __mframe_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/objc-gnu2next.h b/Source/objects/objc-gnu2next.h new file mode 100644 index 000000000..ee7664e4a --- /dev/null +++ b/Source/objects/objc-gnu2next.h @@ -0,0 +1,235 @@ +/* Definitions to allow compilation of GNU objc code with NeXT runtime + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This file is by no means complete. */ + +#ifndef __objc_gnu2next_h_INCLUDE_GNU +#define __objc_gnu2next_h_INCLUDE_GNU + +#include + +#if NeXT_runtime + +#define arglist_t marg_list +#define retval_t void* +#define TypedStream NXTypedStream + +#define objc_write_type(STREAM, TYPE, VAR) \ + NXWriteType(STREAM, TYPE, VAR) +#define objc_write_types(STREAM, TYPE, args...) \ + NXWriteTypes(STREAM, TYPE, args) +#define objc_write_object(STREAM, VAR) \ + NXWriteObject(STREAM, VAR) +#define objc_write_object_reference(STREAM, VAR) \ + NXWriteObjectReference(STREAM, VAR) +#define objc_read_type(STREAM, TYPE, VAR) \ + NXReadType(STREAM, TYPE, VAR) +#define objc_read_types(STREAM, TYPE, args...) \ + NXReadTypes(STREAM, TYPE, args) +#define objc_read_object(STREAM, VAR) \ + do { (*(VAR)) = NXReadObject(STREAM); } while (0) +#define objc_write_root_object \ + NXWriteRootObject +#define objc_open_typed_stream_for_file \ + NXOpenTypedStreamForFile +#define objc_close_typed_stream NXCloseTypedStream + +#define class_create_instance(CLASS) class_createInstance(CLASS, 0) +#define sel_get_name(ASEL) sel_getName(ASEL) +#define sel_get_uid(METHODNAME) set_getUid(METHODNAME) +#define class_get_instance_method(CLASSPOINTER, SEL) \ + class_getInstanceMethod(CLASSPOINTER, SEL) +#define class_get_class_method(CLASSPOINTER, SEL) \ + class_getClassMethod(CLASSPOINTER, SEL) +#define class_get_class_name(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->name) +#define method_get_sizeof_arguments(METHOD) \ + method_getSizeOfArguments(METHOD) +#define objc_lookup_class(CLASSNAME) \ + objc_lookUpClass(CLASSNAME) +#define sel_get_any_uid(SELNAME) \ + sel_getUid(SELNAME) +#define object_get_class(OBJECT) \ + (((struct objc_class*)(OBJECT))->isa) +#define class_get_super_class(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->super_class) +#define objc_get_class(CLASSNAME) \ + objc_lookUpClass(CLASSNAME) /* not exactly right */ +#define class_get_version(CLASSPOINTER) \ + (((struct objc_class*)(CLASSPOINTER))->version) +#define __objc_responds_to(OBJECT,SEL) \ + class_getInstanceMethod(object_get_class(OBJECT), SEL) +#define CLS_ISMETA(CLASSPOINTER) \ + ((((struct objc_class*)(CLASSPOINTER))->info) & CLS_META) +#define objc_msg_lookup(OBJ,SEL) \ + (class_getInstanceMethod(object_get_class(OBJ), SEL)->method_imp) + +#if 1 +volatile void objc_fatal(const char* msg); +#else +#define objc_fatal(FMT, args...) \ + do { fprintf (stderr, (FMT), ##args); abort(); } while (0) +#endif + +#define OBJC_READONLY 1 +#define OBJC_WRITEONLY 2 + + +/* Methods defined by the GNU runtime, which libobjects will provide + if the GNU runtime isn't being used. */ + +int objc_sizeof_type(const char* type); +int objc_alignof_type(const char* type); +int objc_aligned_size (const char* type); +int objc_promoted_size (const char* type); +inline const char* objc_skip_type_qualifiers (const char* type); +const char* objc_skip_typespec (const char* type); +inline const char* objc_skip_offset (const char* type); +const char* objc_skip_argspec (const char* type); +unsigned objc_get_type_qualifiers (const char* type); + +/* The following from GNU's objc/list.h */ + +#include +#include + +struct objc_list { + void *head; + struct objc_list *tail; +}; + +/* Return a cons cell produced from (head . tail) */ + +static inline struct objc_list* +list_cons(void* head, struct objc_list* tail) +{ + struct objc_list* cell; + + cell = (struct objc_list*)(*objc_malloc)(sizeof(struct objc_list)); + cell->head = head; + cell->tail = tail; + return cell; +} + +/* Return the length of a list, list_length(NULL) returns zero */ + +static inline int +list_length(struct objc_list* list) +{ + int i = 0; + while(list) + { + i += 1; + list = list->tail; + } + return i; +} + +/* Return the Nth element of LIST, where N count from zero. If N + larger than the list length, NULL is returned */ + +static inline void* +list_nth(int index, struct objc_list* list) +{ + while(index-- != 0) + { + if(list->tail) + list = list->tail; + else + return 0; + } + return list->head; +} + +/* Remove the element at the head by replacing it by its successor */ + +static inline void +list_remove_head(struct objc_list** list) +{ + if ((*list)->tail) + { + struct objc_list* tail = (*list)->tail; /* fetch next */ + *(*list) = *tail;/* copy next to list head */ + (*objc_free)(tail);/* free next */ + } + else/* only one element in list */ + { + (*objc_free)(*list); + (*list) = 0; + } +} + + +/* Remove the element with `car' set to ELEMENT */ + +static inline void +list_remove_elem(struct objc_list** list, void* elem) +{ + while (*list) { + if ((*list)->head == elem) + list_remove_head(list); + list = &((*list)->tail); + } +} + +/* Map FUNCTION over all elements in LIST */ + +static inline void +list_mapcar(struct objc_list* list, void(*function)(void*)) +{ + while(list) + { + (*function)(list->head); + list = list->tail; + } +} + +/* Return element that has ELEM as car */ + +static inline struct objc_list** +list_find(struct objc_list** list, void* elem) +{ + while(*list) + { + if ((*list)->head == elem) + return list; + list = &((*list)->tail); + } + return NULL; +} + +/* Free list (backwards recursive) */ + +static void +list_free(struct objc_list* list) +{ + if(list) + { + list_free(list->tail); + (*objc_free)(list); + } +} + +#endif /* NeXT_runtime */ + +#endif /* __objc_gnu2next_h_INCLUDE_GNU */ diff --git a/Source/objects/objc-malloc.h b/Source/objects/objc-malloc.h new file mode 100644 index 000000000..58fb5fd62 --- /dev/null +++ b/Source/objects/objc-malloc.h @@ -0,0 +1,44 @@ +/* Memory allocation definitions for Objective-C, easy garbage collection. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __objc_malloc_h_INCLUDE_GNU +#define __objc_malloc_h_INCLUDE_GNU + +/* I do this to make substituting Boehm's Garbage Collection easy. */ +extern void *(*objc_malloc)(size_t); +extern void *(*objc_atomic_malloc)(size_t); +extern void *(*objc_realloc)(void *, size_t); +extern void *(*objc_calloc)(size_t, size_t); +extern void (*objc_free)(void *); + +#define OBJC_MALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_malloc)((unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_ATOMIC_MALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_atomic_malloc)((unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_REALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_realloc)((VAR), (unsigned)(NUM)*sizeof(TYPE))) +#define OBJC_CALLOC(VAR, TYPE, NUM) \ + ((VAR) = (TYPE *) (*objc_calloc)((unsigned)(NUM), sizeof(TYPE))) +#define OBJC_FREE(PTR) (*objc_free)((PTR)) + +#endif /* __objc_malloc_h_INCLUDE_GNU */ diff --git a/Source/objects/objects.h b/Source/objects/objects.h new file mode 100644 index 000000000..8d0671981 --- /dev/null +++ b/Source/objects/objects.h @@ -0,0 +1,78 @@ +/* Includes interfaces for all concrete objects classes + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __objects_h_OBJECTS_INCLUDE +#define __objects_h_OBJECTS_INCLUDE + +#include + +/* Collection objects */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Magnitude objects */ +#include +#include +#include + +/* Stream objects */ +#include +#include +#include + +/* Coder objects */ +#include +#include +#include + +/* Port objects */ +#include +#include + +/* Remote messaging support objects */ +#include +#include +#include + +#endif /* __objects_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/stdobjects.h.in b/Source/objects/stdobjects.h.in new file mode 100644 index 000000000..b58be37ca --- /dev/null +++ b/Source/objects/stdobjects.h.in @@ -0,0 +1,119 @@ +/* General purpose definitions for the GNU Objective-C Library. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __stdobjects_h_OBJECTS_INCLUDE +#define __stdobjects_h_OBJECTS_INCLUDE + +#include +#include +#include +#include + +#if NeXT_runtime + #include + #include + #include + #ifndef _C_ATOM + #define _C_ATOM '%' + #endif + #define _F_CONST 0x01 + #define _F_IN 0x01 + #define _F_OUT 0x02 + #define _F_INOUT 0x03 + #define _F_BYCOPY 0x04 + #define _F_ONEWAY 0x08 + #define _C_CONST 'r' + #define _C_IN 'n' + #define _C_INOUT 'N' + #define _C_OUT 'o' + #define _C_BYCOPY 'O' + #define _C_ONEWAY 'V' + #define CLASS Class +#else /* GNU Objective C Runtime */ + #include + #include + #include + #include + #include + #define CLASS Class* +#endif + +#include +#include + +/* The following two lines are maintained by the libobjects Makefile */ +#define OBJECTS_VERSION 0.1.0 +#define OBJECTS_GCC_VERSION 2.6.1 + +extern const char objects_version[]; +extern const char objects_gcc_version[]; +#if NeXT_cc +extern const char objects_NeXT_cc_version[]; +#endif + +#define LAMBDA(RETTYPE, ARGS, BODY) \ +({RETTYPE __lambda_func ARGS BODY __lambda_func;}) + +#define LAMBDA_VOID_PERFORM(SELECTOR) \ +LAMBDA(void, (id _o), {[_o perform: SELECTOR];}) + +#define LAMBDA_ID_PERFORM(SELECTOR) \ +LAMBDA(id, (id _o), {return [_o perform: SELECTOR];}) + +#define LAMBDA_BOOL_PERFORM(SELECTOR) \ +LAMBDA(BOOL, (id _o), {if ([_o perform:SELECTOR]) return YES; else return NO;}) + + +#ifndef MAX +#define MAX(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a > _b ? _a : _b; }) +#endif + +#ifndef MIN +#define MIN(a,b) \ + ({typedef _ta = (a), _tb = (b); \ + _ta _a = (a); _tb _b = (b); \ + _a < _b ? _a : _b; }) +#endif + +#ifndef PTR2LONG +#define PTR2LONG(P) (((char*)(P))-(char*)0) +#endif +#ifndef LONG2PTR +#define LONG2PTR(L) (((char*)0)+(L)) +#endif + +/* GNU Object.[hm] defines -compare:, NeXT doesn't, libobjects needs it. */ +#if NeXT_runtime +@interface Object (GNUExtensions) +- (int)compare:anotherObject; +- shouldNotImplement:(SEL)op; +@end +#endif /* NeXT_runtime */ + +#endif /* __stdobjects_h_OBJECTS_INCLUDE */ + + + diff --git a/Source/preface.m b/Source/preface.m new file mode 100644 index 000000000..8715f45f3 --- /dev/null +++ b/Source/preface.m @@ -0,0 +1,33 @@ +/* Support for general purpose definitions for the Collection Library. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#define XSTR(s) STR(s) +#define STR(s) #s +const char objects_version[] = XSTR(GOBJC_VERSION); +const char objects_gcc_version[] = XSTR(GOBJC_GCC_VERSION); + +#if NeXT_cc +const char objects_NeXT_cc_version[] = XSTR(NX_CURRENT_COMPILER_RELEASE); +#endif /* NeXT_cc */ diff --git a/Source/stdobjects.m b/Source/stdobjects.m new file mode 100644 index 000000000..8715f45f3 --- /dev/null +++ b/Source/stdobjects.m @@ -0,0 +1,33 @@ +/* Support for general purpose definitions for the Collection Library. + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + Date: May 1993 + + This file is part of the GNU Objective C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#define XSTR(s) STR(s) +#define STR(s) #s +const char objects_version[] = XSTR(GOBJC_VERSION); +const char objects_gcc_version[] = XSTR(GOBJC_GCC_VERSION); + +#if NeXT_cc +const char objects_NeXT_cc_version[] = XSTR(NX_CURRENT_COMPILER_RELEASE); +#endif /* NeXT_cc */ diff --git a/Testing/Makefile.in b/Testing/Makefile.in new file mode 100644 index 000000000..e9b1ccf70 --- /dev/null +++ b/Testing/Makefile.in @@ -0,0 +1,149 @@ +# +# Tests makefile for Objective-C Class Library +# Copyright (C) 1993 Free Software Foundation, Inc. +# +# Written by: R. Andrew McCallum +# Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 +# +# This file is part of the GNU Objective-C Class 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +SHELL = /bin/sh + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ + +CFLAGS = -Wall -Wno-implicit -g -O +CPPFLAGS = +LDFLAGS = + +DEFS = @DEFS@ +LIBS = -L$(srcdir)/.. -lobjects @LIBOBJC@ @LIBS@ + +#### End of system configuration section. #### + +NEXT_NEXT_INCLUDES = -I/usr/include +OBJECTS_NEXT_INCLUDES = -I$(srcdir)/../objects/next-include +NEXT_INCLUDES = @NEXT_INCLUDES@ + +ALL_CPPFLAGS = -I$(srcdir)/.. $(NEXT_INCLUDES) $(CPPFLAGS) +ALL_CFLAGS = $(CFLAGS) +ALL_OBJCFLAGS = $(CFLAGS) -Wno-protocol +ALL_LDFLAGS = $(LDFLAGS) $(LIBS) + +.SUFFIXES: .m +.m.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_OBJCFLAGS) $< -o $*.o +.c.o: + $(CC) -c $(ALL_CPPFLAGS) $(DEFS) $(ALL_CFLAGS) $< -o $*.o + +SRCS = \ +test01.m \ +test02.m \ +test03.m \ +test04.m \ +test05.m \ +test06.m \ +test07.m \ +test08.m \ +test09.m \ +test10.m \ +test11.m \ +test12.m \ +test13.m \ +pipes.m \ +server.m \ +client.m + +HDRS = \ +server.h + +EXCS = $(SRCS:.m=) + +DISTFILES = $(SRCS) $(HDRS) Makefile.in NXStringTable.example + +all: $(EXCS) + +# This works for GNU make, but not others. +# %: %.o $(srcdir)/../libobjects.a +# $(CC) $(ALL_CFLAGS) $< -o $@ $(ALL_LDFLAGS) +# How can I do this in a better way than the ugliness below? +# (but also have it work on old-style /bin/make) + +LINK_CMD = $(CC) $(ALL_CFLAGS) $@.o -o $@ $(ALL_LDFLAGS) +test01: test01.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test02: test02.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test03: test03.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test04: test04.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test05: test05.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test06: test06.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test07: test07.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test08: test08.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test09: test09.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test10: test10.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test11: test11.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test12: test12.o $(srcdir)/../libobjects.a + $(LINK_CMD) +test13: test13.o $(srcdir)/../libobjects.a + $(LINK_CMD) +pipes: pipes.o $(srcdir)/../libobjects.a + $(LINK_CMD) +server: server.o $(srcdir)/../libobjects.a + $(LINK_CMD) +client: client.o $(srcdir)/../libobjects.a + $(LINK_CMD) + +echo-excs: + @echo $(EXCS) + +remote: server client + +mostlyclean: + rm -f core *~ test08.data textcoder.txt + +clean: mostlyclean + rm -f *.o $(EXCS) + +distclean: clean + rm -f Makefile config.status + +realclean: distclean + rm -f TAGS + +dist-dir: $(srcdir)/../.fname + @echo Run make dist from the parent directory. + +dist: $(DISTFILES) dist-dir + mkdir $(srcdir)/../`cat $(srcdir)/../.fname`/checks + ln $(DISTFILES) $(srcdir)/../`cat $(srcdir)/../.fname`/checks + +Makefile: Makefile.in + cd $(srcdir)/..; $(SHELL) config.status diff --git a/Testing/NXStringTable.example b/Testing/NXStringTable.example new file mode 100644 index 000000000..469509da1 --- /dev/null +++ b/Testing/NXStringTable.example @@ -0,0 +1,21 @@ +/* This is an example of a string table file. Everything inside a comment +is completely ignored, even if in "quotes", or \escape characters, etc. +*/ + +"title" = "pattern II target 1"; + +/* This is an example of excape codes in the string table, codes */ +/* that are not one of abfnrtv are stripped of the \ character */ +"escapes" = "This is a tab \t and a return \n or a \a but not a \p"; +"escapes2" = "Well how about a \0? Guess not."; + +/* more parameters, white space between tokens is ignored */ +"actualSize" + = + "0.000250 0.000250"; + +/* a key with no value assumes the value is the same as the key */ +"hoe322070.element"; + +/* this will produce an error */ +"unterminated"= "this is a string with no ending quote; diff --git a/Testing/client.m b/Testing/client.m new file mode 100644 index 000000000..ddc9fa5f8 --- /dev/null +++ b/Testing/client.m @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include "server.h" + +int main(int argc, char *argv[]) +{ + id p; + id callback_receiver = [Object new]; + id o; + id localObj; + unsigned long i = 4; + id c; + int j,k; + foo f = {99, "cow", 9876543}; + /* foo f2; */ + foo *fp; + const char *n; + // int a3[3] = {66,77,88}; + struct myarray ma = {{55,66,77}}; + double dbl = 3.14159265358979323846264338327; + double *dbl_ptr; + char *string = "Hello from the client"; + small_struct small = {12}; + BOOL b; + const char *type; + + [Coder setDebugging:YES]; + [BinaryCoder setDebugging:YES]; + +#if NeXT_runtime + [Proxy setProtocolForProxies:@protocol(AllProxies)]; +#endif + + if (argc > 1) + p = [Connection rootProxyAtName:"test2server" onHost:argv[1]]; + else + p = [Connection rootProxyAtName:"test2server" onHost:""]; + c = [p connectionForProxy]; + + type = [c _typeForSelector:sel_get_any_uid("name") + remoteTarget:[p targetForProxy]]; + printf(">>type = %s\n", type); + + printf(">>list proxy's hash is 0x%x\n", + (unsigned)[p hash]); + printf(">>list proxy's self is 0x%x = 0x%x\n", + (unsigned)[p self], (unsigned)p); + n = [p name]; + printf(">>proxy's name is (%s)\n", n); + [p print:">>This is a message from the client."]; + printf(">>getLong:(out) to server i = %lu\n", i); + [p getLong:&i]; + printf(">>getLong:(out) from server i = %lu\n", i); + assert(i == 3); + o = [p objectAt:0]; + printf(">>object proxy's hash is 0x%x\n", (unsigned)[o hash]); + [p shout]; + [p callbackNameOn:callback_receiver]; + /* this next line doesn't actually test callbacks, it tests + sending the same object twice in the same message. */ + [p callbackNameOn:p]; + b = [p doBoolean:YES]; + printf(">>BOOL value is '%c' (0x%x)\n", b, (int)b); +#if 0 + /* Both these cause problems because GCC encodes them as "*", + indistinguishable from strings. */ + b = NO; + [p getBoolean:&b]; + printf(">>BOOL reference is '%c' (0x%x)\n", b, (int)b); + b = NO; + [p getUCharPtr:&b]; + printf(">>UCHAR reference is '%c' (0x%x)\n", b, (int)b); +#endif + fp = [p sendStructPtr:&f]; + fp->i = 11; + [p sendStruct:f]; + [p sendSmallStruct:small]; + [p sendStructArray:ma]; +#if 0 + /* returning structures isn't working yet. */ + f2 = [p returnStruct]; + printf(">>returned foo: i=%d s=%s l=%lu\n", + f2.i, f2.s, f2.l); +#endif + [p sendDouble:dbl andFloat:98.6]; + dbl_ptr = [p doDoublePointer:&dbl]; + printf(">>got double %f from server\n", *dbl_ptr); + [p sendCharPtrPtr:&string]; + /* testing "-perform:" */ + if (p != [p perform:sel_get_any_uid("self")]) + [Object error:"trying perform:"]; + /* testing "bycopy" */ + /* reverse the order on these next two and it doesn't crash, + however, having manyArgs called always seems to crash. + Was this problem here before object forward references? + Check a snapshot. + Hmm. It seems like a runtime selector-handling bug. */ + if (![p isProxy]) + [p manyArgs:1 :2 :3 :4 :5 :6 :7 :8 :9 :10 :11 :12]; + [p sendBycopy:callback_receiver]; + printf(">>returned float %f\n", [p returnFloat]); + printf(">>returned double %f\n", [p returnDouble]); + + localObj = [[Object alloc] init]; + [p addObject:localObj]; + k = [p count]; + for (j = 0; j < k; j++) + { + id remote_peer_obj = [p objectAt:j]; + printf("triangle %d object proxy's hash is 0x%x\n", + j, (unsigned)[remote_peer_obj hash]); + [remote_peer_obj release]; + remote_peer_obj = [p objectAt:j]; + printf("repeated triangle %d object proxy's hash is 0x%x\n", + j, (unsigned)[remote_peer_obj hash]); + } + [c runConnectionWithTimeout:1500]; + [c dealloc]; + + exit(0); +} diff --git a/Testing/pipes.m b/Testing/pipes.m new file mode 100644 index 000000000..0138fb524 --- /dev/null +++ b/Testing/pipes.m @@ -0,0 +1,16 @@ +#include + +int main() +{ + char b[100]; + int len; + id s = [[StdioStream alloc] initWithPipeFrom:"cat /etc/group | sort"]; + + while ((len = [s readBytes:b length:99]) > 0) + { + b[len] = '\0'; + printf("[%d]: %s\n", len, b); + } + + exit(0); +} diff --git a/Testing/server.h b/Testing/server.h new file mode 100644 index 000000000..3bb00753b --- /dev/null +++ b/Testing/server.h @@ -0,0 +1,66 @@ +#ifndef _server_h +#define _server_h + +#include +#include +#include +#include +#include + +typedef struct _small_struct { + unsigned char z; +} small_struct; + +typedef struct _foo { + int i; + char *s; + unsigned long l; +} foo; + +struct myarray { + int a[3]; +}; + +@protocol ServerProtocol +- addObject: o; +- objectAt: (unsigned)i; +- (unsigned) count; +- print: (const char *)msg; +- getLong: (out unsigned long*)i; +- (oneway void) shout; +- callbackNameOn: obj; +- bounce: sender count: (int)c; +- (BOOL) doBoolean: (BOOL)b; +- getBoolean: (BOOL*)bp; +- getUCharPtr: (unsigned char *)ucp; +- (foo*) sendStructPtr: (foo*)f; +- sendStruct: (foo)f; +- sendSmallStruct: (small_struct)small; +- (foo) returnStruct; +- sendArray: (int[3])a; +- sendStructArray: (struct myarray)ma; +- sendDouble: (double)d andFloat: (float)f; +- (double*) doDoublePointer: (double*)d; +- sendCharPtrPtr: (char**)sp; +- sendBycopy: (bycopy id)o; +- manyArgs: (int)i1 : (int)i2 : (int)i3 : (int)i4 : (int)i5 : (int)i6 +: (int)i7 : (int)i8 : (int)i9 : (int)i10 : (int)i11 : (int)i12; +- (float) returnFloat; +- (double) returnDouble; +@end + +#if NeXT_runtime +@protocol AllProxies +- (const char *)name; +- (unsigned) hash; +- self; +@end +#endif + +@interface Server : Object +{ + id theList; +} +@end + +#endif /* _server_h */ diff --git a/Testing/server.m b/Testing/server.m new file mode 100644 index 000000000..bf748d0a0 --- /dev/null +++ b/Testing/server.m @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include "server.h" + +@implementation Server +- init +{ + theList = [[List alloc] init]; + return self; +} +- (unsigned) count +{ + return [theList count]; +} +- addObject: o +{ + [theList addObject:o]; + return self; +} +- objectAt: (unsigned)i +{ + return [theList objectAt:i]; +} +- print: (const char *)msg +{ + printf(">>%s\n", msg); + return self; +} +- getLong: (out unsigned long*)i +{ + printf(">>getLong:(out) from client %lu\n", *i); + *i = 3; + printf(">>getLong:(out) to client %lu\n", *i); + return self; +} +- (oneway void) shout +{ + printf(">>Ahhhhh\n"); + return; +} +- callbackNameOn: obj +{ + printf(">>callback name is (%s)\n", [obj name]); + return self; +} +/* sender must also respond to 'bounce:count:' */ +- bounce: sender count: (int)c +{ + if (--c) + [sender bounce:self count:c]; + return self; +} +- (BOOL) doBoolean: (BOOL)b +{ + printf(">> got boolean '%c' (0x%x) from client\n", b, (unsigned int)b); + return YES; +} +/* This causes problems, because the runtime encodes this as "*", + a string! */ +- getBoolean: (BOOL*)bp +{ + printf(">> got boolean pointer '%c' (0x%x) from client\n", + *bp, (unsigned int)*bp); + return self; +} +/* This also causes problems, because the runtime also encodes this as "*", + a string! */ +- getUCharPtr: (unsigned char *)ucp +{ + printf(">> got unsignec char pointer '%c' (0x%x) from client\n", + *ucp, (unsigned int)*ucp); + return self; +} + +/* This isn't working yet */ +- (foo*) sendStructPtr: (foo*)f +{ + printf(">>reference: i=%d s=%s l=%lu\n", + f->i, f->s, f->l); + f->i = 88; + return f; +} +- sendStruct: (foo)f +{ + printf(">>value: i=%d s=%s l=%lu\n", + f.i, f.s, f.l); + f.i = 88; + return self; +} +- sendSmallStruct: (small_struct)small +{ + printf(">>small value struct: z=%d\n", small.z); + return self; +} +/* Doesn't work. GCC __builtin_return doesn't let you return structs? */ +- (foo) returnStruct +{ + foo f = {1, "horse", 987654}; + return f; +} +/* Doesn't work because GCC generates the wrong encoding: "@0@+8:+12^i+16" */ +- sendArray: (int[3])a +{ + printf(">> array %d %d %d\n", a[0], a[1], a[2]); + return self; +} +- sendStructArray: (struct myarray)ma +{ + printf(">>struct array %d %d %d\n", ma.a[0], ma.a[1], ma.a[2]); + return self; +} + +- sendDouble: (double)d andFloat: (float)f +{ + printf(">> double %f, float %f\n", d, f); + return self; +} + +- (double*) doDoublePointer: (double*)d +{ + printf(">> got double %f from client\n", *d); + *d = 1.234567; + printf(">> returning double %f to client\n", *d); + return d; +} + +- sendCharPtrPtr: (char**)sp +{ + printf(">> got char**, string %s\n", *sp); + return self; +} + +- sendBycopy: (bycopy id)o +{ + printf(">> bycopy class is %s\n", [o name]); + [o free]; + return self; +} +- manyArgs: (int)i1 : (int)i2 : (int)i3 : (int)i4 : (int)i5 : (int)i6 +: (int)i7 : (int)i8 : (int)i9 : (int)i10 : (int)i11 : (int)i12 +{ + printf(">> manyArgs: %d %d %d %d %d %d %d %d %d %d %d %d\n", + i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12); + return self; +} + +- (float) returnFloat +{ + static float f = 2.3456789; + return f; +} + +- (double) returnDouble +{ + /* static */ + double d = 4.567891234; + return d; +} + +- senderIsInvalid: anObj +{ + if ([anObj isKindOf:[Connection class]]) + { + id objList; + int i, j, count, listCount = [theList count]; + objList = [anObj proxies]; + count = [objList count]; + /* This contortion avoids List's calling -isEqual: on the proxy */ + for (i = 0; i < count; i++) + for (j = 0; j < [theList count]; j++) + if ([theList objectAt:j] == [objList objectAtIndex:i]) + [theList removeObjectAt:j]; + [objList free]; + if (listCount != [theList count]) + printf("$$$$$ senderIsInvalid: removed from theList\n"); + } + else + { + [self error:"non Connection is invalid"]; + } + return self; +} +- (Connection*) connection: ancestor didConnect: newConn +{ + printf("%s\n", sel_get_name(_cmd)); + [newConn registerForInvalidationNotification:self]; + [newConn setDelegate:self]; + return newConn; +} +@end + +int main() +{ + id l = [[Server alloc] init]; + id o = [[Object alloc] init]; + double d; + Connection *c; + + [BinaryCoder setDebugging:YES]; + +#if NeXT_runtime + [Proxy setProtocolForProxies:@protocol(AllProxies)]; +#endif + c = [Connection newRegisteringAtName:"test2server" withRootObject:l]; + [c registerForInvalidationNotification:l]; + [c setDelegate:l]; + + [l addObject:o]; + d = [l returnDouble]; + printf("got double %f\n", d); + printf("list's hash is 0x%x\n", (unsigned)[l hash]); + printf("object's hash is 0x%x\n", (unsigned)[o hash]); + [c runConnection]; + + exit(0); +} diff --git a/Testing/test01.m b/Testing/test01.m new file mode 100644 index 000000000..57e4c8a3c --- /dev/null +++ b/Testing/test01.m @@ -0,0 +1,113 @@ + +#include +#include + +#if (__svr4__) +long lrand48(); +#define random lrand48 +#else +long random(); +#endif + +@interface Collection (TestingExtras) +- printCount; +@end +@implementation Collection (TestingExtras) +- printCount +{ + printf("%s: count=%d\n", [self name], [self count]); + return self; +} +@end + +void checkSameContents(id objectslist) +{ + unsigned i, c = [objectslist count]; + + for (i = 1; i < c; i++) + if (![[objectslist objectAtIndex:0] + contentsEqual:[objectslist objectAtIndex:i]]) + printf("collection 0 does not have same contents as collection %d\n", i); +} + + +int main() +{ + int i, e; + + id array = [[Array alloc] initWithType:@encode(int)]; + id bag = [[Bag alloc] initWithType:"i"]; + id stack = [[Stack alloc] initWithType:"i"]; + id queue = [[Queue alloc] initWithType:"i"]; + id gaparray = [[GapArray alloc] initWithType:"i"]; + id llist = [[EltNodeCollector alloc] initWithType:"i" + nodeCollector:[[LinkedList alloc] init] + nodeClass:[LinkedListEltNode class]]; + id bt = [[EltNodeCollector alloc] initWithType:"i" + nodeCollector:[[BinaryTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + id rt = [[EltNodeCollector alloc] initWithType:"i" + nodeCollector:[[RBTree alloc] init] + nodeClass:[RBTreeEltNode class]]; + id st = [[EltNodeCollector alloc] initWithType:"i" + nodeCollector:[[SplayTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + id foo = [[Array alloc] initWithType:"i"]; + + id collections = [DelegatePool new]; + + [collections delegatePoolAddObject:array]; + [collections delegatePoolAddObject:llist]; + [collections delegatePoolAddObject:bag]; + [collections delegatePoolAddObject:stack]; + [collections delegatePoolAddObject:queue]; + [collections delegatePoolAddObject:gaparray]; + [collections delegatePoolAddObject:bt]; + [collections delegatePoolAddObject:rt]; + [collections delegatePoolAddObject:st]; + [collections delegatePoolAddObject:foo]; + + printf("delegatePool filled, count=%d\n", + [[collections delegatePoolCollection] count]); + + [collections addElement:99]; + [collections printCount]; + + printf("Adding numbers...\n"); + for (i = 0; i < 17; i++) + { + e = random() % 99; + printf("%2d ", e); + [collections addElement:e]; + } + printf("\ncollections filled\n\n"); + [collections printForDebugger]; + + { + BOOL testzero (elt e) + { + if (e.void_ptr_u == 0) return NO; + else return YES; + } + if ([array trueForAllElementsByCalling:testzero]) + printf("Array contains no zero's\n"); + } + + checkSameContents([collections delegatePoolCollection]); + + printf("\nremoving 99\n\n"); + [collections removeElement:99]; + + [foo removeElement:[foo minElement]]; + [foo addElement:99]; + printf("Collections 0 and 9 should mismatch\n"); + [collections printForDebugger]; + + checkSameContents([collections delegatePoolCollection]); + + [collections empty]; + + exit(0); +} + + diff --git a/Testing/test02.m b/Testing/test02.m new file mode 100644 index 000000000..008a936b8 --- /dev/null +++ b/Testing/test02.m @@ -0,0 +1,41 @@ + +#include + + +int main() +{ + id dict = [[Dictionary alloc] initWithType:"*" + keyType:"*"]; + id translator = [[Dictionary alloc] initWithType:"*" + keyType:"*"]; + id mc; + + [dict putElement:"herd" atKey:"cow"]; + [dict putElement:"pack" atKey:"dog"]; + [dict putElement:"school" atKey:"fish"]; + [dict putElement:"flock" atKey:"bird"]; + [dict putElement:"pride" atKey:"cat"]; + [dict putElement:"gaggle" atKey:"goose"]; + [dict printForDebugger]; + printf("removing goose\n"); + [dict removeElementAtKey:"goose"]; + [dict printForDebugger]; + + [translator putElement:"cow" atKey:"vache"]; + [translator putElement:"dog" atKey:"chien"]; + [translator putElement:"fish" atKey:"poisson"]; + [translator putElement:"bird" atKey:"oisseau"]; + [translator putElement:"cat" atKey:"chat"]; + + mc = [[MappedCollector alloc] initCollection:dict map:translator]; + [mc printForDebugger]; + + [mc free]; + [dict free]; + [translator free]; + + exit(0); + +} + + diff --git a/Testing/test03.m b/Testing/test03.m new file mode 100644 index 000000000..4bd115a6d --- /dev/null +++ b/Testing/test03.m @@ -0,0 +1,44 @@ + +#include + + +int main() +{ + id array = [[Array alloc] initWithType:@encode(int)]; + id bag; + id llist; + id btree; + + [array addElementsCount:6, ((elt)0),((elt)1),((elt)5),((elt)3), + ((elt)4),((elt)2)]; + bag = [array shallowCopyAs:[Bag class]]; + llist = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[LinkedList alloc] init] + nodeClass:[LinkedListEltNode class]]; + [llist addContentsOf:array]; + + btree = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[BinaryTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + [btree addContentsOf:array]; + printf("btree count = %d\n", [btree count]); + + /* tmp test */ +/* + if (typeof((id)0) != typeof(id)) + printf("typeof error\n"); +*/ + + [array printForDebugger]; + [bag printForDebugger]; + [llist printForDebugger]; + [btree printForDebugger]; + + /* foo = [array shallowCopyAs:[Object class]]; + Shouldn't the compiler complain about this? + Object does not conform to */ + + exit(0); +} + + diff --git a/Testing/test04.m b/Testing/test04.m new file mode 100644 index 000000000..cc2b2a429 --- /dev/null +++ b/Testing/test04.m @@ -0,0 +1,44 @@ + +#include + +#define N 20 + +#if (sun && __svr4__) +long lrand48(); +#define random lrand48 +#else +long random(); +#endif + +int main() +{ + int i; + short s, s1, s2; + + Heap* heap = [[Heap alloc] initWithType:"s"]; + Array* array = [[Array alloc] initWithType:"s"]; + + for (i = 0; i < N; i++) + { + s = (short)random(); + [heap addElement:s]; + [array addElement:s]; + } + [array sortContents]; + + for (i = 0; i < N; i++) + { + s1 = [heap removeFirstElement].short_int_u; + s2 = [array removeLastElement].short_int_u; + printf("(%d,%d) ", s1, s2); + if (s1 != s2) + exit(1); + } + printf("\n"); + + /* cause an error */ + /* s = [heap elementAtIndex:999].short_int_u; */ + + [heap free]; + exit(0); +} diff --git a/Testing/test05.m b/Testing/test05.m new file mode 100644 index 000000000..6c839dfb2 --- /dev/null +++ b/Testing/test05.m @@ -0,0 +1,17 @@ +#include + +int main() +{ + id a = [[Array alloc] initWithType:@encode(int)]; + int i; + unsigned ret42 (arglist_t f) { return 42; } + + [a addElementsCount:5, + ((elt)0),((elt)1),((elt)2),((elt)3),((elt)4)]; + [a printForDebugger]; + i = [a indexOfElement:99 + ifAbsentCall:ret42]; + + printf("This should be 42---> %d\n", i); + exit(0); +} diff --git a/Testing/test06.m b/Testing/test06.m new file mode 100644 index 000000000..1752173f1 --- /dev/null +++ b/Testing/test06.m @@ -0,0 +1,23 @@ + +#include + +#define N 20 + +int main() +{ + int i; + + Array* array = [[Array alloc] init]; + + for (i = 0; i < N; i++) + { + [array addObject:[[Object alloc] init]]; + } + + [array makeObjectsPerform:@selector(name)]; + + [[array objectAtIndex:0] hash]; + [[array freeObjects] free]; + printf("no errors\n"); + exit(0); +} diff --git a/Testing/test07.m b/Testing/test07.m new file mode 100644 index 000000000..bd8894e10 --- /dev/null +++ b/Testing/test07.m @@ -0,0 +1,16 @@ +#include + +int main() +{ + id a = [[Array alloc] initWithType:@encode(int)]; + int i; + void plus2 (elt e) {printf("%d ", e.int_u+2);} + + for (i = 0; i < 10; i++) + [a addElement:i]; + + [a withElementsCall:plus2]; + + printf("\n"); + exit(0); +} diff --git a/Testing/test08.m b/Testing/test08.m new file mode 100644 index 000000000..6a3b505bd --- /dev/null +++ b/Testing/test08.m @@ -0,0 +1,60 @@ + +#include + +void test(id objects) +{ + TypedStream *stream; + + [objects addElementsCount:6, ((elt)0),((elt)1),((elt)5),((elt)3), + ((elt)4),((elt)2)]; + printf("written "); + [objects printForDebugger]; + + stream = objc_open_typed_stream_for_file("test08.data", OBJC_WRITEONLY); + objc_write_root_object(stream, objects); + objc_close_typed_stream(stream); + [objects free]; + + stream = objc_open_typed_stream_for_file("test08.data", OBJC_READONLY); + objc_read_object(stream, &objects); + printf("read "); + [objects printForDebugger]; + [objects free]; +} + +int main() +{ + id objects; + + objects = [[Array alloc] initWithType:@encode(int)]; + test(objects); + + objects = [[Bag alloc] initWithType:@encode(int)]; + test(objects); + + objects = [[Set alloc] initWithType:@encode(int)]; + test(objects); + + objects = [[GapArray alloc] initWithType:@encode(int)]; + test(objects); + + objects = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[LinkedList alloc] init] + nodeClass:[LinkedListEltNode class]]; + test(objects); + + objects = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[BinaryTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + test(objects); + +/* + objects = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeClass:[RBTreeEltNode class]]; + test(objects); +*/ + + exit(0); +} + + diff --git a/Testing/test09.m b/Testing/test09.m new file mode 100644 index 000000000..2991abe2f --- /dev/null +++ b/Testing/test09.m @@ -0,0 +1,81 @@ +#include + +#if (sun && __svr4__) +long lrand48(); +#define random lrand48 +#else +long random(); +#endif + +int main() +{ + int i; + id node; + id s = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[SplayTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + void foo (id o) {[o self];} + + for (i = 1; i < 20; i++) + [s addElement:(int)random()%99]; + [[s contentsCollector] binaryTreePrintForDebugger]; + [s free]; + + s = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[SplayTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + for (i = 1; i < 20; i++) + [s addElement:(int)random()%99]; + [[s contentsCollector] binaryTreePrintForDebugger]; + [s removeElement:[s elementAtIndex:10]]; + [[s contentsCollector] binaryTreePrintForDebugger]; + [[s contentsCollector] withObjectsCall:foo]; + [s free]; + + s = [[EltNodeCollector alloc] initWithType:@encode(int) + nodeCollector:[[BinaryTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + [s appendElement:'i']; + [s insertElement:'h' before:'i']; + [s insertElement:'g' before:'h']; + [s insertElement:'f' before:'g']; + [s insertElement:'e' after:'f']; + [s insertElement:'d' before:'e']; + [s insertElement:'c' after:'d']; + [s insertElement:'b' after:'c']; + [s insertElement:'a' after:'b']; + [[s contentsCollector] binaryTreePrintForDebugger]; + [[s contentsCollector] binaryTreePrintForDebugger]; + + s = [[EltNodeCollector alloc] initWithType:@encode(char) + nodeCollector:[[SplayTree alloc] init] + nodeClass:[BinaryTreeEltNode class]]; + [s appendElement:(char)'i']; + [s insertElement:(char)'h' before:(char)'i']; + [s insertElement:(char)'g' before:(char)'h']; + [s insertElement:(char)'f' before:(char)'g']; + [s insertElement:(char)'e' after:(char)'f']; + [s insertElement:(char)'d' before:(char)'e']; + [s insertElement:(char)'c' after:(char)'d']; + [s insertElement:(char)'b' after:(char)'c']; + [s insertElement:(char)'a' after:(char)'b']; + [[s contentsCollector] binaryTreePrintForDebugger]; + + [[s contentsCollector] splayNode:[s eltNodeWithElement:(char)'a']]; + [[s contentsCollector] binaryTreePrintForDebugger]; + +/* + while ([s eltNodeWithElement:(char)'a'] + != [[s contentsCollector] rootNode]) + { + [[s contentsCollector] _doSplayOperationOnNode: + [s eltNodeWithElement:(char)'a']]; + printf("===============================\n"); + [[s contentsCollector] binaryTreePrintForDebugger]; + } +*/ + + if ((node = [s eltNodeWithElement:(char)'z']) != nil) + [s error:"eltNodeWithElement: loses."]; + exit(0); +} diff --git a/Testing/test10.m b/Testing/test10.m new file mode 100644 index 000000000..671d81d50 --- /dev/null +++ b/Testing/test10.m @@ -0,0 +1,35 @@ +#include +#include + +int main() +{ +#if ELT_INCLUDES_DOUBLE + + id a = [[Array alloc] initWithType:@encode(double)]; + elt e; + double dbl; + + printf("testing elt doubles\n"); + + [a addElement:(double)3.14]; + [a addElement:(double)1.41]; + [a addElement:(double)4.15]; + [a addElement:(double)1.59]; + [a addElement:(double)5.92]; + [a addElement:(double)9.26]; + + e = [a elementAtIndex:1]; + dbl = [a elementAtIndex:2].double_u; + printf("dbl = %f\n", dbl); + + [a addElementIfAbsent:(double)9.26]; + assert([a count] == 6); + + [a removeElement:(double)3.14]; + assert([a count] == 5); + +#endif /* ELT_INCLUDES_DOUBLE */ + + printf("no errors\n"); + exit(0); +} diff --git a/Testing/test11.m b/Testing/test11.m new file mode 100644 index 000000000..c07dc2dc8 --- /dev/null +++ b/Testing/test11.m @@ -0,0 +1,29 @@ +#include +#include + +int +main(int argc, char *argv[]) +{ + id table; + int i, times; + + if (argc < 2) { + fprintf(stderr, "Usage: table_test filename repeat\n"); + fprintf(stderr, " filename is a stringtable format file.\n"); + fprintf(stderr, " repeat is a number of times to loop\n"); + exit(1); + } + if (argc == 3) + times = atoi(argv[2]); + else + times = 1; + + table = [[NXStringTable alloc] init]; + + for (i=0; i < times; i++) { + [table readFromFile:argv[1]]; + printf("-----------------------------------------\n"); + [table writeToStream:stdout]; + } + return 0; +} diff --git a/Testing/test12.m b/Testing/test12.m new file mode 100644 index 000000000..765a22c15 --- /dev/null +++ b/Testing/test12.m @@ -0,0 +1,35 @@ + +#include +#include +#include + +int main() +{ + id r; + id rng; + int i; + + r = [[Random alloc] init]; + printf("float\n"); + for (i = 0; i < 20; i++) + printf("%f\n", [r randomFloat]); + printf("doubles\n"); + for (i = 0; i < 20; i++) + printf("%f\n", [r randomDouble]); + + rng = [[RNGBerkeley alloc] init]; + printf("%s chi^2 = %f\n", + [rng name], [Random chiSquareOfRandomGenerator:rng]); + [r free]; + + rng = [[RNGAdditiveCongruential alloc] init]; +/* + for (i = 0; i < 50; i++) + printf("%ld\n", [r nextRandom]); +*/ + printf("%s chi^2 = %f\n", + [rng name], [Random chiSquareOfRandomGenerator:rng]); + [r free]; + + exit(0); +} diff --git a/Testing/test13.m b/Testing/test13.m new file mode 100644 index 000000000..3e931abd6 --- /dev/null +++ b/Testing/test13.m @@ -0,0 +1,44 @@ +/* +From: Matthias Klose +Date: Mon, 1 Aug 1994 21:17:20 +0200 +To: mccallum@cs.rochester.edu +Subject: bug in libcoll-940725 +Reply-to: doko@cs.tu-berlin.de + +Hello, the following code core dumps on Solaris 2.3 (compiled with gcc +2.5.8 -g -O and with -g) and on NeXTstep 3.2 (gcc 2.5.8). +Any hints? +*/ + +#include + +int main () +{ + Array *a; + CircularArray *c; + Queue *q; + + a = [Array new]; + + [a prependObject: [Object new]]; + [a prependObject: [Object new]]; + [a prependObject: [Object new]]; + printf("count: %d\n", [a count]); + [a insertObject: [Object new] atIndex: 2]; // ok! + printf("count: %d\n", [a count]); + + c = [[CircularArray alloc] initWithType:@encode(int)]; + [c prependElement: 3]; + [c prependElement: 2]; + [c prependElement: 1]; + [c insertElement:0 atIndex:2]; // core dump! + + q = [Queue new]; + [q enqueueObject: [Object new]]; + [q enqueueObject: [Object new]]; + [q enqueueObject: [Object new]]; + printf("count: %d\n", [q count]); + [q insertObject: [Object new] atIndex: 2]; // core dump! + printf("count: %d\n", [q count]); + return 0; +} diff --git a/config.guess b/config.guess new file mode 100755 index 000000000..529e53fed --- /dev/null +++ b/config.guess @@ -0,0 +1,348 @@ +#!/bin/sh +# This script attempts to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/-.*//'` + exit 0 ;; + alpha:OSF1:1.*:*) + # 1.2 uses "1.2" for uname -r. + echo alpha-dec-osf${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:V1.*:* | alpha:OSF1:V[2-9].*:*) + # 1.3 and later use "V1.3", etc. for uname -r. + echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'` + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + sun4*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + echo sparc-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + mips:*:5*:RISCos) + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX:*:*) + echo mips-sgi-irix${UNAME_RELEASE} + exit 0 ;; + i[34]86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:* | 9000/8?7:HP-UX:*:* ) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?7 ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + case ${UNAME_RELEASE} in + *.B7.* ) HPUX_REV=7 ;; + *.B8.* | *.08.* ) HPUX_REV=8 ;; + *.09.* ) HPUX_REV=9 ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2:*) + echo c2-convex-bsd + exit 0 ;; + CRAY*X-MP:UNICOS:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:UNICOS:*:*) + echo ymp-cray-unicos + exit 0 ;; + CRAY-2:UNICOS:*:*) + echo cray2-cray-unicos + exit 0 ;; + i[34]86:BSD/386:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + i[34]86:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd + exit 0 ;; + i[34]86:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + i[34]86:UNIX_SV:4.*:* | i[34]86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i[34]86:*:3.2:*) + if /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL + elif test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M680[234]0:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,3[34]??:*:4.0:*) + uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m680[234]0:LynxOS:2.2*:*) + echo m68k-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i[34]86:LynxOS:2.2*:*) + echo i386-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.2*:*) + echo sparc-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c </dev/null`; + if (version==2) + { + printf("%s-next-ns2\n", __ARCHITECTURE__); + exit(0); + } + else + { + printf("%s-next-ns3\n", __ARCHITECTURE__); + exit(0); + } +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf("ns32k-encore-sysv\n"); exit(0); +#else +#if defined (CMU) + printf("ns32k-encore-mach\n"); exit(0); +#else + printf("ns32k-encore-bsd\n"); exit(0); +#endif +#endif +#endif + +#if defined(__386BSD__) || (defined(__bsdi__) && defined(__i386__)) + printf("i386-unknown-bsd\n"); exit(0); +#endif + +#if defined(sequent) +#if defined(i386) + printf("i386-sequent-dynix\n"); exit(0); +#endif +#if defined (ns32000) + printf("ns32k-sequent-dynix\n"); exit(0); +#endif +#endif + +#if defined(_SEQUENT_) + printf("i386-sequent-ptx\n"); exit(0); +#endif + +#if defined(vax) +#if !defined(ultrix) + printf("vax-dec-bsd\n"); exit(0); +#else + printf("vax-dec-ultrix\n"); exit(0); +#endif +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/config/config.nested.c b/config/config.nested.c new file mode 100644 index 000000000..d81beb032 --- /dev/null +++ b/config/config.nested.c @@ -0,0 +1,17 @@ +/* Used by `configure' to test GCC nested functions */ +int main() +{ + int a = 2; + void nested(int b) + { + a += b; + } + void doit(void(*f)(int)) + { + (*f)(4); + } + doit(nested); + if (a != 6) + exit(-1); + exit(0); +} diff --git a/config/config.nextcc.h b/config/config.nextcc.h new file mode 100644 index 000000000..c10c032e0 --- /dev/null +++ b/config/config.nextcc.h @@ -0,0 +1,19 @@ +/* + * This file is used by configure.in. + * Causes cpp error when running NeXT's cc. + * No error when running gcc on a NeXT box. + */ + +#if defined(NeXT) + #if defined(_NEXT_SOURCE) + "Not running NeXT's cc" + #else + "Running NeXT's cc" + #error + #endif +#else + "Not running NeXT's cc" +#endif + +/* This would be useful, but it isn't available in NS3.0: + #if defined(NX_CURRENT_COMPILER_RELEASE) */ diff --git a/config/config.nextrt.m b/config/config.nextrt.m new file mode 100644 index 000000000..ce2255227 --- /dev/null +++ b/config/config.nextrt.m @@ -0,0 +1,18 @@ +/* A function for testing if the compiler is using the NeXT Objective C + runtime or not. + + With the NeXT runtime this file compiles and links. + With the GNU runtime, this file does not link. +*/ + +#include + +int libobjects_nextrt_checker () +{ + id o = [[Object alloc] init]; + + [o self]; + objc_msgSend(o, @selector(self)); + + exit(0); +} diff --git a/configure.in b/configure.in new file mode 100644 index 000000000..b7fdcac2b --- /dev/null +++ b/configure.in @@ -0,0 +1,226 @@ +AC_INIT(Collection.m) + +# configure.in for GNU Objective-C library +# Process this file with autoconf to produce a configure script. +# +# Copyright (C) 1993,1994 Free Software Foundation, Inc. +# +# Written by: R. Andrew McCallum +# Dept. of Computer Science, U. of Rochester, Rochester, NY 14627 +# +# This file is part of the GNU Objective-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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#-------------------------------------------------------------------- +# Find the compiler +#-------------------------------------------------------------------- +AC_PROG_CC +AC_PROG_CPP + +#-------------------------------------------------------------------- +# Find out if we\'re using NeXT\'s compiler. +# if yes: +# add -cpp-traditional to CPP +# if no: +# include implementations of List, HashTable etc. objects +#-------------------------------------------------------------------- +AC_MSG_CHECKING(whether we are using NeXT's compiler) +AC_TRY_CPP([#include "config.nextcc.h"], NeXTCC=0, NeXTCC=1) +# Was using this too: -o `basename $CC` = "gcc" -o `basename $CC` = "xgcc" +if test $NeXTCC = 0; then + AC_MSG_RESULT(no) + #---------------------------------------------------------------- + # Find out if nested functions work on this machine + #---------------------------------------------------------------- + AC_C_CROSS + AC_MSG_CHECKING(whether nested functions work) + AC_TRY_RUN([#include "config.nested.c"], gcc_nested=1, gcc_nested=0, + gcc_nested=1) + if test $gcc_nested = 0; then + echo "aborting" + echo + echo "The GCC 'nested functions' feature does not seem to be working on" + echo "this machine. Libobjects makes extensive use of nested functions." + echo "Read the bug-report instructions in the GCC texinfo manual" + echo "and submit a bug report." + echo "The program this configure script used to test nested functions" + echo "can be found in the file 'config.nested.c' in the libobjects" + echo "distribution. Under sparc-sun-sunos4.1.3 with gcc-2.6.1 the" + echo "file compiles, runs and returns exit status 0." + exit + else + AC_MSG_RESULT(yes) + fi + #---------------------------------------------------------------- + # Find out if we're on a NEXTSTEP machine + #---------------------------------------------------------------- + AC_MSG_CHECKING(whether we are running under NEXTSTEP) + AC_TRY_CPP([#if defined(NeXT) + #error + #endif], NeXTSTEP=0, NeXTSTEP=1) + if test $NeXTSTEP = 0; then + AC_MSG_RESULT(no) + NeXT_runtime=0 + INSTALL_OBJS='$(GNU_OBJS) $(NeXT_OBJS)' + INSTALL_HEADERS='$(GNU_HEADERS) $(NeXT_HEADERS)' + NEXT_INCLUDES='$(OBJECTS_NEXT_INCLUDES)' + NeXT_runtime=0 + NeXT_cc=0 + else + AC_MSG_RESULT(yes) + #---------------------------------------------------------------- + # Find out if we are using NeXT or GNU runtime + #---------------------------------------------------------------- + saved_ac_ext=$ac_ext + ac_ext=m + AC_MSG_CHECKING(whether we are using GNU Objective C runtime) + AC_TRY_LINK([#include "config.nextrt.m"], ;, + NeXT_runtime=1, NeXT_runtime=0) + ac_ext=$saved_ac_ext + if test $NeXT_runtime = 1; then + AC_MSG_RESULT(no: NeXT runtime) + LIBOBJC='' + CC="$CC -fnext-runtime" + # Make sure that we get NeXTs objc/*.h files + NEXT_INCLUDES='$(NEXT_NEXT_INCLUDES)' + INSTALL_OBJS='$(GNU_OBJS)' + INSTALL_HEADERS='$(GNU_HEADERS)' + NeXT_cc=0 + else + AC_MSG_RESULT(yes) + LIBOBJC='-lobjc' + CC="$CC -fgnu-runtime" + # Get objc/List.h, etc. files from libobjects. + NEXT_INCLUDES='$(OBJECTS_NEXT_INCLUDES)' + INSTALL_OBJS='$(GNU_OBJS) $(NeXT_OBJS)' + INSTALL_HEADERS='$(GNU_HEADERS) $(NeXT_HEADERS)' + NeXT_cc=0 + fi + fi + #---------------------------------------------------------------- + # Find out if we have sel_types_match + # (i.e. the necessary patch has been applied) + #---------------------------------------------------------------- + if test $NeXT_runtime = 0; then + AC_CHECK_LIB(objc, main, HAVE_LIBOBJC=1, HAVE_LIBOBJC=0) + if test $HAVE_LIBOBJC = 0; then + AC_MSG_ERROR(Couldn't find GCC Objective C runtime library, libobjc.a) + else + LIBS="$LIBS -lobjc" + fi + AC_CHECK_FUNC(sel_types_match, have_sel=1, have_sel=0) + if test $have_sel = 0; then + AC_MSG_ERROR(Could not find sel_types_match in libobjc.a. + GCC version less than 2.6.1?) + fi + fi + +else + + AC_MSG_RESULT(yes) + AC_MSG_ERROR(Sorry, libobjects does not currently work with NeXT's cc; use gcc) + #---------------------------------------------------------------- + # Find out if we have NEXTSTEP 3.2 or lower + #---------------------------------------------------------------- + AC_CHECKING(NEXTSTEP version) + AC_TRY_CPP([#if NX_CURRENT_COMPILER_RELEASE < 320 + #error + #endif], NeXT32plus=1, NeXT32plus=0) + if test $NeXT32plus = 0; then + echo "aborting" + echo + echo "It looks like your compiler is NEXTSTEP 3.2 or earlier." + echo "Libobjects makes extensive use of nested functions. In 3.2," + echo "NeXT's cc did not support nested functions. To compile libobjects" + echo "you can either (1) use gcc instead of NeXT's cc (no loss, since" + echo "gcc can compile AppKit programs without problems), or (2) upgrade" + echo "to the later release of NEXTSTEP when it is available." + exit + fi + INSTALL_OBJS='$(GNU_OBJS)' + INSTALL_HEADERS='$(GNU_HEADERS)' + LIBOBJC='' + NeXT_runtime=1 + NeXT_cc=1 + # NeXT default cpp doesn't accept nested functions + CC='cc -traditional-cpp' +fi +AC_SUBST(INSTALL_OBJS) +AC_SUBST(INSTALL_HEADERS) +AC_SUBST(LIBOBJC) +AC_SUBST(NeXT_runtime) +AC_SUBST(NeXT_cc) +AC_SUBST(NEXT_INCLUDES) + +#-------------------------------------------------------------------- +# Find some programs +#-------------------------------------------------------------------- +AC_PROG_INSTALL +AC_PROG_RANLIB + +#-------------------------------------------------------------------- +# Following header checks needed for bzero in Storage.m and other places +#-------------------------------------------------------------------- +AC_HEADER_STDC +AC_CHECK_HEADERS(string.h memory.h) + +#-------------------------------------------------------------------- +# These two headers (functions) needed by Time.m +#-------------------------------------------------------------------- +dnl AC_REPLACE_FUNCS(getrusage gettimeofday) +AC_CHECK_HEADER(sys/time.h, TIME_H=1, TIME_H=0) +AC_CHECK_HEADER(sys/resource.h, RESOURCE_H=1, RESOURCE_H=0) + +if test TIME_H = 0 -o RESOURCE_H = 0 ; then + AC_MSG_ERROR(Could not find headers needed by class Time) +fi + +AC_CHECK_HEADERS(sys/rusage.h ucbinclude/sys/resource.h) + +#-------------------------------------------------------------------- +# These headers/functions needed by SocketPort.m +#-------------------------------------------------------------------- +AC_CHECK_HEADER(sys/socket.h, SOCKET_H=1, SOCKET_H=0) +AC_CHECK_HEADER(netinet/in.h, IN_H=1, IN_H=0) +dnl AC_REPLACE_FUNCS(recvfrom) + +if test SOCKET_H = 0 -o IN_H = 0 ; then + AC_MSG_ERROR(Could not find headers needed by class SocketPort) +fi + +#-------------------------------------------------------------------- +# These functions needed by StdioStream.m +#-------------------------------------------------------------------- +AC_CHECK_FUNCS(vsprintf) + +#-------------------------------------------------------------------- +# These libraries needed by the check programs for distributed objects +# on Solaris where the socket/network code isn't the regular place. Yuck! +# I'm assuming that if the socket/network code is in the regular place, +# we won't find these libraries, or if we do find them, they aren't +# something weird I wouldn't want to link with. +# It's just for the programs in "checks" and "examples" anyway; it +# doesn't affect the compilation of libobjects. +#-------------------------------------------------------------------- +AC_CHECK_LIB(socket, main) +AC_CHECK_LIB(nsl, main) + + +#-------------------------------------------------------------------- +# Write the Makefiles +#-------------------------------------------------------------------- +AC_OUTPUT(Makefile checks/Makefile examples/Makefile objects/config.h) diff --git a/install-sh b/install-sh new file mode 100755 index 000000000..240d8f46a --- /dev/null +++ b/install-sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$cpprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 000000000..0e2937731 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,35 @@ +#!/bin/sh +# Make directory hierarchy. +# Written by Noah Friedman +# Public domain. + +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +errstatus=0 + +for file in ${1+"$@"} ; do + oIFS="${IFS}" + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo ${file} | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS="${oIFS}" + + pathcomp='' + + for d in ${1+"$@"} ; do + pathcomp="${pathcomp}${d}" + + if test ! -d "${pathcomp}"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "${pathcomp}" || errstatus=$? + fi + + pathcomp="${pathcomp}/" + done +done + +exit $errstatus + +# eof