commit a8824b7f957b741af70a98f0009ffd1e05a80329 Author: Jack Moffitt Date: Mon Sep 10 02:24:39 2001 +0000 Initial revision svn path=/trunk/avl/; revision=1997 diff --git a/avl/BUILDING b/avl/BUILDING new file mode 100644 index 0000000..0aa7006 --- /dev/null +++ b/avl/BUILDING @@ -0,0 +1,7 @@ +defines that affect compilation + +none + +library dependencies + +none diff --git a/avl/COPYING b/avl/COPYING new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/avl/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/avl/Makefile.am b/avl/Makefile.am new file mode 100644 index 0000000..7efab51 --- /dev/null +++ b/avl/Makefile.am @@ -0,0 +1,20 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libiceavl.la +noinst_HEADERS = avl.h + +libiceavl_la_SOURCES = avl.c + +INCLUDES = -I$(srcdir)/../thread + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/avl/README b/avl/README new file mode 100644 index 0000000..6b9d490 --- /dev/null +++ b/avl/README @@ -0,0 +1,6 @@ +this is the avl tree library. + +lgpl + +by sam rushing +modified by jack moffitt diff --git a/avl/TODO b/avl/TODO new file mode 100644 index 0000000..4648207 --- /dev/null +++ b/avl/TODO @@ -0,0 +1,2 @@ +- avl_get_last() +- a little more cleanup probably diff --git a/avl/avl.c b/avl/avl.c new file mode 100644 index 0000000..6e6c002 --- /dev/null +++ b/avl/avl.c @@ -0,0 +1,1178 @@ +/* + * Copyright (C) 1995-1997 by Sam Rushing + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission + * notice appear in supporting documentation, and that the name of Sam + * Rushing not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* $Id: avl.c,v 1.1 2001/09/10 02:28:03 jack Exp $ */ + +/* + * This is a fairly straightfoward translation of a prototype + * written in python, 'avl_tree.py'. Read that file first. + */ + +#include +#include + +#include "thread.h" +#include "avl.h" + + +avl_node * +avl_node_new (void * key, + avl_node * parent) +{ + avl_node * node = (avl_node *) malloc (sizeof (avl_node)); + + if (!node) { + return NULL; + } else { + node->parent = parent; + node->key = key; + node->left = NULL; + node->right = NULL; + node->rank_and_balance = 0; + AVL_SET_BALANCE (node, 0); + AVL_SET_RANK (node, 1); + thread_rwlock_create(&node->rwlock); + return node; + } +} + +avl_tree * +avl_tree_new (avl_key_compare_fun_type compare_fun, + void * compare_arg) +{ + avl_tree * t = (avl_tree *) malloc (sizeof (avl_tree)); + + if (!t) { + return NULL; + } else { + avl_node * root = avl_node_new((void *)NULL, (avl_node *) NULL); + if (!root) { + return NULL; + } else { + t->root = root; + t->height = 0; + t->length = 0; + t->compare_fun = compare_fun; + t->compare_arg = compare_arg; + thread_rwlock_create(&t->rwlock); + return t; + } + } +} + +void +avl_tree_free_helper (avl_node * node, avl_free_key_fun_type free_key_fun) +{ + if (node->left) { + avl_tree_free_helper (node->left, free_key_fun); + } + free_key_fun (node->key); + if (node->right) { + avl_tree_free_helper (node->right, free_key_fun); + } + free (node); +} + +void +avl_tree_free (avl_tree * tree, avl_free_key_fun_type free_key_fun) +{ + if (tree->length) { + avl_tree_free_helper (tree->root->right, free_key_fun); + } + if (tree->root) { + free (tree->root); + } + free (tree); +} + +int +avl_insert (avl_tree * ob, + void * key) +{ + if (!(ob->root->right)) { + avl_node * node = avl_node_new (key, ob->root); + if (!node) { + return -1; + } else { + ob->root->right = node; + ob->length = ob->length + 1; + return 0; + } + } else { /* not self.right == None */ + avl_node *t, *p, *s, *q, *r; + int a; + + t = ob->root; + s = p = t->right; + + while (1) { + if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) { + /* move left */ + AVL_SET_RANK (p, (AVL_GET_RANK (p) + 1)); + q = p->left; + if (!q) { + /* insert */ + avl_node * q_node = avl_node_new (key, p); + if (!q_node) { + return (-1); + } else { + q = q_node; + p->left = q; + break; + } + } else if (AVL_GET_BALANCE(q)) { + t = p; + s = q; + } + p = q; + } else { + /* move right */ + q = p->right; + if (!q) { + /* insert */ + avl_node * q_node = avl_node_new (key, p); + if (!q_node) { + return -1; + } else { + q = q_node; + p->right = q; + break; + } + } else if (AVL_GET_BALANCE(q)) { + t = p; + s = q; + } + p = q; + } + } + + ob->length = ob->length + 1; + + /* adjust balance factors */ + if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) { + r = p = s->left; + } else { + r = p = s->right; + } + while (p != q) { + if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) { + AVL_SET_BALANCE (p, -1); + p = p->left; + } else { + AVL_SET_BALANCE (p, +1); + p = p->right; + } + } + + /* balancing act */ + + if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) { + a = -1; + } else { + a = +1; + } + + if (AVL_GET_BALANCE (s) == 0) { + AVL_SET_BALANCE (s, a); + ob->height = ob->height + 1; + return 0; + } else if (AVL_GET_BALANCE (s) == -a) { + AVL_SET_BALANCE (s, 0); + return 0; + } else if (AVL_GET_BALANCE(s) == a) { + if (AVL_GET_BALANCE (r) == a) { + /* single rotation */ + p = r; + if (a == -1) { + s->left = r->right; + if (r->right) { + r->right->parent = s; + } + r->right = s; + s->parent = r; + AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (r))); + } else { + s->right = r->left; + if (r->left) { + r->left->parent = s; + } + r->left = s; + s->parent = r; + AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (s))); + } + AVL_SET_BALANCE (s, 0); + AVL_SET_BALANCE (r, 0); + } else if (AVL_GET_BALANCE (r) == -a) { + /* double rotation */ + if (a == -1) { + p = r->right; + r->right = p->left; + if (p->left) { + p->left->parent = r; + } + p->left = r; + r->parent = p; + s->left = p->right; + if (p->right) { + p->right->parent = s; + } + p->right = s; + s->parent = p; + AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (r))); + AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (p))); + } else { + p = r->left; + r->left = p->right; + if (p->right) { + p->right->parent = r; + } + p->right = r; + r->parent = p; + s->right = p->left; + if (p->left) { + p->left->parent = s; + } + p->left = s; + s->parent = p; + AVL_SET_RANK (r, (AVL_GET_RANK (r) - AVL_GET_RANK (p))); + AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (s))); + } + if (AVL_GET_BALANCE (p) == a) { + AVL_SET_BALANCE (s, -a); + AVL_SET_BALANCE (r, 0); + } else if (AVL_GET_BALANCE (p) == -a) { + AVL_SET_BALANCE (s, 0); + AVL_SET_BALANCE (r, a); + } else { + AVL_SET_BALANCE (s, 0); + AVL_SET_BALANCE (r, 0); + } + AVL_SET_BALANCE (p, 0); + } + /* finishing touch */ + if (s == t->right) { + t->right = p; + } else { + t->left = p; + } + p->parent = t; + } + } + return 0; +} + +int +avl_get_by_index (avl_tree * tree, + unsigned long index, + void ** value_address) +{ + avl_node * p = tree->root->right; + unsigned long m = index + 1; + while (1) { + if (!p) { + return -1; + } + if (m < AVL_GET_RANK(p)) { + p = p->left; + } else if (m > AVL_GET_RANK(p)) { + m = m - AVL_GET_RANK(p); + p = p->right; + } else { + *value_address = p->key; + return 0; + } + } +} + +int +avl_get_by_key (avl_tree * tree, + void * key, + void **value_address) +{ + avl_node * x = tree->root->right; + if (!x) { + return -1; + } + while (1) { + int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); + if (compare_result < 0) { + if (x->left) { + x = x->left; + } else { + return -1; + } + } else if (compare_result > 0) { + if (x->right) { + x = x->right; + } else { + return -1; + } + } else { + *value_address = x->key; + return 0; + } + } +} + +int avl_delete(avl_tree *tree, void *key, avl_free_key_fun_type free_key_fun) +{ + avl_node *x, *y, *p, *q, *r, *top, *x_child; + int shortened_side, shorter; + + x = tree->root->right; + if (!x) { + return -1; + } + while (1) { + int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); + if (compare_result < 0) { + /* move left + * We will be deleting from the left, adjust this node's + * rank accordingly + */ + AVL_SET_RANK (x, (AVL_GET_RANK(x) - 1)); + if (x->left) { + x = x->left; + } else { + /* Oops! now we have to undo the rank changes + * all the way up the tree + */ + AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1)); + while (x != tree->root->right) { + if (x->parent->left == x) { + AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1)); + } + x = x->parent; + } + return -1; /* key not in tree */ + } + } else if (compare_result > 0) { + /* move right */ + if (x->right) { + x = x->right; + } else { + AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1)); + while (x != tree->root->right) { + if (x->parent->left == x) { + AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1)); + } + x = x->parent; + } + return -1; /* key not in tree */ + } + } else { + break; + } + } + + if (x->left && x->right) { + void * temp_key; + + /* The complicated case. + * reduce this to the simple case where we are deleting + * a node with at most one child. + */ + + /* find the immediate predecessor */ + y = x->left; + while (y->right) { + y = y->right; + } + /* swap with */ + temp_key = x->key; + x->key = y->key; + y->key = temp_key; + /* we know 's left subtree lost a node because that's + * where we took it from + */ + AVL_SET_RANK (x, (AVL_GET_RANK (x) - 1)); + x = y; + } + /* now has at most one child + * scoot this child into the place of + */ + if (x->left) { + x_child = x->left; + x_child->parent = x->parent; + } else if (x->right) { + x_child = x->right; + x_child->parent = x->parent; + } else { + x_child = NULL; + } + + /* now tell 's parent that a grandchild became a child */ + if (x == x->parent->left) { + x->parent->left = x_child; + shortened_side = -1; + } else { + x->parent->right = x_child; + shortened_side = +1; + } + + /* + * the height of the subtree + * has now been shortened. climb back up + * the tree, rotating when necessary to adjust + * for the change. + */ + shorter = 1; + p = x->parent; + + /* return the key and node to storage */ + free_key_fun (x->key); + free (x); + + while (shorter && p->parent) { + + /* case 1: height unchanged */ + if (AVL_GET_BALANCE(p) == 0) { + if (shortened_side == -1) { + /* we removed a left child, the tree is now heavier + * on the right + */ + AVL_SET_BALANCE (p, +1); + } else { + /* we removed a right child, the tree is now heavier + * on the left + */ + AVL_SET_BALANCE (p, -1); + } + shorter = 0; + + } else if (AVL_GET_BALANCE (p) == shortened_side) { + /* case 2: taller subtree shortened, height reduced */ + AVL_SET_BALANCE (p, 0); + } else { + /* case 3: shorter subtree shortened */ + top = p->parent; + /* set to the taller of the two subtrees of

*/ + if (shortened_side == 1) { + q = p->left; + } else { + q = p->right; + } + if (AVL_GET_BALANCE (q) == 0) { + /* case 3a: height unchanged */ + if (shortened_side == -1) { + /* single rotate left */ + q->parent = p->parent; + p->right = q->left; + if (q->left) { + q->left->parent = p; + } + q->left = p; + p->parent = q; + AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p))); + } else { + /* single rotate right */ + q->parent = p->parent; + p->left = q->right; + if (q->right) { + q->right->parent = p; + } + q->right = p; + p->parent = q; + AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q))); + } + shorter = 0; + AVL_SET_BALANCE (q, shortened_side); + AVL_SET_BALANCE (p, (- shortened_side)); + } else if (AVL_GET_BALANCE (q) == AVL_GET_BALANCE (p)) { + /* case 3b: height reduced */ + if (shortened_side == -1) { + /* single rotate left */ + q->parent = p->parent; + p->right = q->left; + if (q->left) { + q->left->parent = p; + } + q->left = p; + p->parent = q; + AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p))); + } else { + /* single rotate right */ + q->parent = p->parent; + p->left = q->right; + if (q->right) { + q->right->parent = p; + } + q->right = p; + p->parent = q; + AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q))); + } + shorter = 1; + AVL_SET_BALANCE (q, 0); + AVL_SET_BALANCE (p, 0); + } else { + /* case 3c: height reduced, balance factors opposite */ + if (shortened_side == 1) { + /* double rotate right */ + /* first, a left rotation around q */ + r = q->right; + r->parent = p->parent; + q->right = r->left; + if (r->left) { + r->left->parent = q; + } + r->left = q; + q->parent = r; + /* now, a right rotation around p */ + p->left = r->right; + if (r->right) { + r->right->parent = p; + } + r->right = p; + p->parent = r; + AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (q))); + AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (r))); + } else { + /* double rotate left */ + /* first, a right rotation around q */ + r = q->left; + r->parent = p->parent; + q->left = r->right; + if (r->right) { + r->right->parent = q; + } + r->right = q; + q->parent = r; + /* now a left rotation around p */ + p->right = r->left; + if (r->left) { + r->left->parent = p; + } + r->left = p; + p->parent = r; + AVL_SET_RANK (q, (AVL_GET_RANK (q) - AVL_GET_RANK (r))); + AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (p))); + } + if (AVL_GET_BALANCE (r) == shortened_side) { + AVL_SET_BALANCE (q, (- shortened_side)); + AVL_SET_BALANCE (p, 0); + } else if (AVL_GET_BALANCE (r) == (- shortened_side)) { + AVL_SET_BALANCE (q, 0); + AVL_SET_BALANCE (p, shortened_side); + } else { + AVL_SET_BALANCE (q, 0); + AVL_SET_BALANCE (p, 0); + } + AVL_SET_BALANCE (r, 0); + q = r; + } + /* a rotation has caused (or in case 3c) to become + * the root. let

's former parent know this. + */ + if (top->left == p) { + top->left = q; + } else { + top->right = q; + } + /* end case 3 */ + p = q; + } + x = p; + p = x->parent; + /* shortened_side tells us which side we came up from */ + if (x == p->left) { + shortened_side = -1; + } else { + shortened_side = +1; + } + } /* end while(shorter) */ + /* when we're all done, we're one shorter */ + tree->length = tree->length - 1; + return (0); +} + +int +avl_iterate_inorder_helper (avl_node * node, + avl_iter_fun_type iter_fun, + void * iter_arg) +{ + int result; + if (node->left) { + result = avl_iterate_inorder_helper (node->left, iter_fun, iter_arg); + if (result != 0) { + return result; + } + } + result = (iter_fun (node->key, iter_arg)); + if (result != 0) { + return result; + } + if (node->right) { + result = avl_iterate_inorder_helper (node->right, iter_fun, iter_arg); + if (result != 0) { + return result; + } + } + return 0; +} + +int +avl_iterate_inorder (avl_tree * tree, + avl_iter_fun_type iter_fun, + void * iter_arg) +{ + int result; + + if (tree->length) { + result = avl_iterate_inorder_helper (tree->root->right, iter_fun, iter_arg); + return (result); + } else { + return 0; + } +} + +avl_node *avl_get_first(avl_tree *tree) +{ + avl_node *node; + + node = tree->root->right; + if (node == NULL || node->key == NULL) return NULL; + + while (node->left) + node = node->left; + + return node; +} + +avl_node *avl_get_prev(avl_node *node) +{ + if (node->left) { + node = node->left; + while (node->right) { + node = node->right; + } + + return node; + } else { + avl_node *child = node; + while (node->parent && node->parent->key) { + node = node->parent; + if (child == node->right) { + return node; + } + child = node; + } + + return NULL; + } +} + +avl_node *avl_get_next(avl_node *node) +{ + if (node->right) { + node = node->right; + while (node->left) { + node = node->left; + } + + return node; + } else { + avl_node *child = node; + while (node->parent && node->parent->key) { + node = node->parent; + if (child == node->left) { + return node; + } + child = node; + } + + return NULL; + } +} + +/* iterate a function over a range of indices, using get_predecessor */ + +int +avl_iterate_index_range (avl_tree * tree, + avl_iter_index_fun_type iter_fun, + unsigned long low, + unsigned long high, + void * iter_arg) +{ + unsigned long m; + unsigned long num_left; + avl_node * node; + + if (high > tree->length) { + return -1; + } + num_left = (high - low); + /* find the th node */ + m = high; + node = tree->root->right; + while (1) { + if (m < AVL_GET_RANK (node)) { + node = node->left; + } else if (m > AVL_GET_RANK (node)) { + m = m - AVL_GET_RANK (node); + node = node->right; + } else { + break; + } + } + /* call on , , ... */ + while (num_left) { + num_left = num_left - 1; + if (iter_fun (num_left, node->key, iter_arg) != 0) { + return -1; + } + node = avl_get_prev (node); + } + return 0; +} + +/* If is present in the tree, return that key's node, and set <*index> + * appropriately. If not, return NULL, and set <*index> to the position + * representing the closest preceding value. + */ + +avl_node * +avl_get_index_by_key (avl_tree * tree, + void * key, + unsigned long * index) +{ + avl_node * x = tree->root->right; + unsigned long m; + + if (!x) { + return NULL; + } + m = AVL_GET_RANK (x); + + while (1) { + int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); + if (compare_result < 0) { + if (x->left) { + m = m - AVL_GET_RANK(x); + x = x->left; + m = m + AVL_GET_RANK(x); + } else { + *index = m - 2; + return NULL; + } + } else if (compare_result > 0) { + if (x->right) { + x = x->right; + m = m + AVL_GET_RANK(x); + } else { + *index = m - 1; + return NULL; + } + } else { + *index = m - 1; + return x; + } + } +} + +/* return the (low index, high index) pair that spans the given key */ + +int +avl_get_span_by_key (avl_tree * tree, + void * key, + unsigned long * low, + unsigned long * high) +{ + unsigned long m, i, j; + avl_node * node; + + node = avl_get_index_by_key (tree, key, &m); + + /* did we find an exact match? + * if so, we have to search left and right + * to find the span, since we know nothing about + * the arrangement of like keys. + */ + if (node) { + avl_node * left, * right; + /* search left */ + left = avl_get_prev (node); + i = m; + while ((i > 0) && (tree->compare_fun (tree->compare_arg, key, left->key) == 0)) { + left = avl_get_prev (left); + i = i - 1; + } + /* search right */ + right = avl_get_next (node); + j = m; + while ((j <= tree->length) && (tree->compare_fun (tree->compare_arg, key, right->key) == 0)) { + right = avl_get_next (right); + j = j + 1; + } + *low = i; + *high = j + 1; + return 0; + } else { + *low = *high = m; + } + return 0; +} + +/* return the (low index, high index) pair that spans the given key */ + +int +avl_get_span_by_two_keys (avl_tree * tree, + void * low_key, + void * high_key, + unsigned long * low, + unsigned long * high) +{ + unsigned long i, j; + avl_node * low_node, * high_node; + int order; + + /* we may need to swap them */ + order = tree->compare_fun (tree->compare_arg, low_key, high_key); + if (order > 0) { + void * temp = low_key; + low_key = high_key; + high_key = temp; + } + + low_node = avl_get_index_by_key (tree, low_key, &i); + high_node = avl_get_index_by_key (tree, high_key, &j); + + if (low_node) { + avl_node * left; + /* search left */ + left = avl_get_prev (low_node); + while ((i > 0) && (tree->compare_fun (tree->compare_arg, low_key, left->key) == 0)) { + left = avl_get_prev (left); + i = i - 1; + } + } else { + i = i + 1; + } + if (high_node) { + avl_node * right; + /* search right */ + right = avl_get_next (high_node); + while ((j <= tree->length) && (tree->compare_fun (tree->compare_arg, high_key, right->key) == 0)) { + right = avl_get_next (right); + j = j + 1; + } + } else { + j = j + 1; + } + + *low = i; + *high = j; + return 0; +} + + +int +avl_get_item_by_key_most (avl_tree * tree, + void * key, + void **value_address) +{ + avl_node * x = tree->root->right; + *value_address = NULL; + + if (!x) { + return -1; + } + while (1) { + int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); + + if (compare_result == 0) { + *value_address = x->key; + return 0; + } else if (compare_result < 0) { + /* the given key is less than the current key */ + if (x->left) { + x = x->left; + } else { + if (*value_address) + return 0; + else + return -1; + } + } else { + /* the given key is more than the current key */ + /* save this value, it might end up being the right one! */ + *value_address = x->key; + if (x->right) { + /* there is a bigger entry */ + x = x->right; + } else { + if (*value_address) + return 0; + else + return -1; + } + } + } +} + +int +avl_get_item_by_key_least (avl_tree * tree, + void * key, + void **value_address) +{ + avl_node * x = tree->root->right; + *value_address = NULL; + + if (!x) { + return -1; + } + while (1) { + int compare_result = tree->compare_fun (tree->compare_arg, key, x->key); + if (compare_result == 0) { + *value_address = x->key; + return 0; /* exact match */ + } else if (compare_result < 0) { + /* the given key is less than the current key */ + /* save this value, it might end up being the right one! */ + *value_address = x->key; + if (x->left) { + x = x->left; + } else { + if (*value_address) /* we have found a valid entry */ + return 0; + else + return -1; + } + } else { + if (x->right) { + /* there is a bigger entry */ + x = x->right; + } else { + if (*value_address) /* we have found a valid entry */ + return 0; + else + return -1; + } + } + } +} + +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + +long +avl_verify_balance (avl_node * node) +{ + if (!node) { + return 0; + } else { + long lh = avl_verify_balance (node->left); + long rh = avl_verify_balance (node->right); + if ((rh - lh) != AVL_GET_BALANCE(node)) { + fprintf (stderr, "invalid balance at node %d\n", (int) node->key); + exit(1); + } + if (((lh - rh) > 1) || ((lh - rh) < -1)) { + fprintf (stderr, "unbalanced at node %d\n", (int) node->key); + exit(1); + } + return (1 + MAX (lh, rh)); + } +} + +void +avl_verify_parent (avl_node * node, avl_node * parent) +{ + if (node->parent != parent) { + fprintf (stderr, "invalid parent at node %d\n", (int) node->key); + exit(1); + } + if (node->left) { + avl_verify_parent (node->left, node); + } + if (node->right) { + avl_verify_parent (node->right, node); + } +} + +long +avl_verify_rank (avl_node * node) +{ + if (!node) { + return 0; + } else { + unsigned long num_left=0, num_right=0; + if (node->left) { + num_left = avl_verify_rank (node->left); + } + if (node->right) { + num_right = avl_verify_rank (node->right); + } + if (AVL_GET_RANK (node) != num_left + 1) { + fprintf (stderr, "invalid rank at node %d\n", (int) node->key); + exit (1); + } + return (num_left + num_right + 1); + } +} + +/* sanity-check the tree */ + +int +avl_verify (avl_tree * tree) +{ + if (tree->length) { + avl_verify_balance (tree->root->right); + avl_verify_parent (tree->root->right, tree->root); + avl_verify_rank (tree->root->right); + } + return (0); +} + +/* + * These structures are accumulated on the stack during print_tree + * and are used to keep track of the width and direction of each + * branch in the history of a particular line . + */ + +typedef struct _link_node { + struct _link_node * parent; + char direction; + int width; +} link_node; + +char balance_chars[3] = {'\\', '-', '/'}; + +int +default_key_printer (char * buffer, void * key) +{ + return sprintf (buffer, "%p", key); +} + +/* + * When traveling the family tree, a change in direction + * indicates when to print a connector. This is kinda crazy, + * we use the stack to build a linked list, and then travel + * it backwards using recursion. + */ + +void +print_connectors (link_node * link) +{ + if (link->parent) { + print_connectors (link->parent); + } + if (link->parent && (link->parent->direction != link->direction) && (link->parent->parent)) { + int i; + fprintf (stdout, "|"); + for (i=0; i < (link->width - 1); i++) { + fprintf (stdout, " "); + } + } else { + int i; + for (i=0; i < (link->width); i++) { + fprintf (stdout, " "); + } + } +} + +/* + * The function writes a representation of the + * key into (which is conveniently fixed in size to add + * the spice of danger). It should return the size of the + * representation. + */ + +void +print_node (avl_key_printer_fun_type key_printer, + avl_node * node, + link_node * link) +{ + char buffer[256]; + unsigned int width; + width = key_printer (buffer, node->key); + + if (node->right) { + link_node here; + here.parent = link; + here.direction = 1; + here.width = width + 11; + print_node (key_printer, node->right, &here); + } + print_connectors (link); + fprintf (stdout, "+-[%c %s %03d]", + balance_chars[AVL_GET_BALANCE(node)+1], + buffer, + (int)AVL_GET_RANK(node)); + if (node->left || node->right) { + fprintf (stdout, "-|\n"); + } else { + fprintf (stdout, "\n"); + } + if (node->left) { + link_node here; + here.parent = link; + here.direction = -1; + here.width = width + 11; + print_node (key_printer, node->left, &here); + } +} + +void +avl_print_tree (avl_tree * tree, avl_key_printer_fun_type key_printer) +{ + link_node top = {NULL, 0, 0}; + if (!key_printer) { + key_printer = default_key_printer; + } + if (tree->length) { + print_node (key_printer, tree->root->right, &top); + } else { + fprintf (stdout, "\n"); + } +} + + +void avl_tree_rlock(avl_tree *tree) +{ + thread_rwlock_rlock(&tree->rwlock); +} + +void avl_tree_wlock(avl_tree *tree) +{ + thread_rwlock_wlock(&tree->rwlock); +} + +void avl_tree_unlock(avl_tree *tree) +{ + thread_rwlock_unlock(&tree->rwlock); +} + +void avl_node_rlock(avl_node *node) +{ + thread_rwlock_rlock(&node->rwlock); +} + +void avl_node_wlock(avl_node *node) +{ + thread_rwlock_wlock(&node->rwlock); +} + +void avl_node_unlock(avl_node *node) +{ + thread_rwlock_unlock(&node->rwlock); +} diff --git a/avl/avl.dsp b/avl/avl.dsp new file mode 100644 index 0000000..10fabf3 --- /dev/null +++ b/avl/avl.dsp @@ -0,0 +1,100 @@ +# Microsoft Developer Studio Project File - Name="avl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=avl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "avl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "avl.mak" CFG="avl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "avl - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "avl - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "avl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "avl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "avl - Win32 Release" +# Name "avl - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\avl.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\avl.h +# End Source File +# End Group +# End Target +# End Project diff --git a/avl/avl.h b/avl/avl.h new file mode 100644 index 0000000..71ab7a9 --- /dev/null +++ b/avl/avl.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 1995 by Sam Rushing + */ + +/* $Id: avl.h,v 1.1 2001/09/10 02:28:03 jack Exp $ */ + +#ifndef __AVL_H +#define __AVL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct avl_node_tag { + void * key; + struct avl_node_tag * left; + struct avl_node_tag * right; + struct avl_node_tag * parent; + /* + * The lower 2 bits of specify the balance + * factor: 00==-1, 01==0, 10==+1. + * The rest of the bits are used for + */ + unsigned long rank_and_balance; + + rwlock_t rwlock; +} avl_node; + +#define AVL_GET_BALANCE(n) ((int)(((n)->rank_and_balance & 3) - 1)) + +#define AVL_GET_RANK(n) (((n)->rank_and_balance >> 2)) + +#define AVL_SET_BALANCE(n,b) \ + ((n)->rank_and_balance) = \ + (((n)->rank_and_balance & (~3)) | ((int)((b) + 1))) + +#define AVL_SET_RANK(n,r) \ + ((n)->rank_and_balance) = \ + (((n)->rank_and_balance & 3) | (r << 2)) + +struct _avl_tree; + +typedef int (*avl_key_compare_fun_type) (void * compare_arg, void * a, void * b); +typedef int (*avl_iter_fun_type) (void * key, void * iter_arg); +typedef int (*avl_iter_index_fun_type) (unsigned long index, void * key, void * iter_arg); +typedef int (*avl_free_key_fun_type) (void * key); +typedef int (*avl_key_printer_fun_type) (char *, void *); + +/* + * and let us associate a particular compare + * function with each tree, separately. + */ + +typedef struct _avl_tree { + avl_node * root; + unsigned long height; + unsigned long length; + avl_key_compare_fun_type compare_fun; + void * compare_arg; + + rwlock_t rwlock; +} avl_tree; + +avl_tree * avl_tree_new (avl_key_compare_fun_type compare_fun, void * compare_arg); +avl_node * avl_node_new (void * key, avl_node * parent); + +void avl_tree_free ( + avl_tree * tree, + avl_free_key_fun_type free_key_fun + ); + +int avl_insert ( + avl_tree * ob, + void * key + ); + +int avl_delete ( + avl_tree * tree, + void * key, + avl_free_key_fun_type free_key_fun + ); + +int avl_get_by_index ( + avl_tree * tree, + unsigned long index, + void ** value_address + ); + +int avl_get_by_key ( + avl_tree * tree, + void * key, + void ** value_address + ); + +int avl_iterate_inorder ( + avl_tree * tree, + avl_iter_fun_type iter_fun, + void * iter_arg + ); + +int avl_iterate_index_range ( + avl_tree * tree, + avl_iter_index_fun_type iter_fun, + unsigned long low, + unsigned long high, + void * iter_arg + ); + +int avl_get_span_by_key ( + avl_tree * tree, + void * key, + unsigned long * low, + unsigned long * high + ); + +int avl_get_span_by_two_keys ( + avl_tree * tree, + void * key_a, + void * key_b, + unsigned long * low, + unsigned long * high + ); + +int avl_verify (avl_tree * tree); + +void avl_print_tree ( + avl_tree * tree, + avl_key_printer_fun_type key_printer + ); + +avl_node *avl_get_first(avl_tree *tree); + +avl_node *avl_get_prev(avl_node * node); + +avl_node *avl_get_next(avl_node * node); + +/* These two are from David Ascher */ + +int avl_get_item_by_key_most ( + avl_tree * tree, + void * key, + void ** value_address + ); + +int avl_get_item_by_key_least ( + avl_tree * tree, + void * key, + void ** value_address + ); + +/* optional locking stuff */ +void avl_tree_rlock(avl_tree *tree); +void avl_tree_wlock(avl_tree *tree); +void avl_tree_unlock(avl_tree *tree); +void avl_node_rlock(avl_node *node); +void avl_node_wlock(avl_node *node); +void avl_node_unlock(avl_node *node); + +#ifdef __cplusplus +} +#endif + +#endif /* __AVL_H */ + + + + diff --git a/avl/test.c b/avl/test.c new file mode 100644 index 0000000..fe9ed48 --- /dev/null +++ b/avl/test.c @@ -0,0 +1,95 @@ +#include +#include "avl.h" + +#ifdef _WIN32 +#define snprintf _snprintf +#endif + +int _compare(void *compare_arg, void *a, void *b); +int _free(void *key); +int _printer(char *buff, void *key); + +int main(int argc, char **argv) +{ + int i, max_nodes; + avl_tree *tree; + avl_node *node; + + max_nodes = 25; + + if (argc == 2) { + max_nodes = atoi(argv[1]); + if (max_nodes == 0) + max_nodes = 10; + } + + printf("avl test... max_nodes = %d...\n", max_nodes); + + tree = avl_tree_new(_compare, NULL); + + printf("Filling tree...\n"); + for (i = 0; i < max_nodes; i++) { + avl_insert(tree, (void *)rand()); + } + + printf("Traversing tree...\n"); + node = avl_get_first(tree); + while (node) { + i = (int)node->key; + + printf("...%5d\n", i); + + node = avl_get_next(node); + } + + printf("Trying to go backwards...\n"); + node = tree->root->right; + while (node) { + i = (int)node->key; + printf("...%5d\n", i); + node = avl_get_prev(node); + } + + printf("Printing tree...\n"); + avl_print_tree(tree, _printer); + + avl_tree_free(tree, _free); + + return 0; +} + +int _compare(void *compare_arg, void *a, void *b) +{ + int i, j; + + i = (int)a; + j = (int)b; + + if (i > j) + return 1; + if (j > i) + return -1; + return 0; +} + +int _free(void *key) +{ + return 1; +} + +int _printer(char *buff, void *key) +{ + return snprintf(buff, 25, "%d", (int)key); +} + + + + + + + + + + + + diff --git a/httpp/BUILDING b/httpp/BUILDING new file mode 100644 index 0000000..9484fac --- /dev/null +++ b/httpp/BUILDING @@ -0,0 +1,7 @@ +defines that affect compilation + +none + +library dependencies + +uses avl diff --git a/httpp/COPYING b/httpp/COPYING new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/httpp/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/httpp/Makefile.am b/httpp/Makefile.am new file mode 100644 index 0000000..394fdd9 --- /dev/null +++ b/httpp/Makefile.am @@ -0,0 +1,20 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libicehttpp.la +noinst_HEADERS = httpp.h + +libicehttpp_la_SOURCES = httpp.c + +INCLUDES = -I$(srcdir)/../avl -I$(srcdir)/../thread + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/httpp/README b/httpp/README new file mode 100644 index 0000000..e4001d5 --- /dev/null +++ b/httpp/README @@ -0,0 +1,5 @@ +httpp is a simple http parser + +licensed under the lgpl + +created by jack moffitt diff --git a/httpp/TODO b/httpp/TODO new file mode 100644 index 0000000..04e2c79 --- /dev/null +++ b/httpp/TODO @@ -0,0 +1 @@ +- nothing i can think of diff --git a/httpp/httpp.c b/httpp/httpp.c new file mode 100644 index 0000000..ba03d38 --- /dev/null +++ b/httpp/httpp.c @@ -0,0 +1,306 @@ +/* Httpp.c +** +** http parsing engine +*/ + +#include +#include +#include + +#include "thread.h" +#include "avl.h" +#include "httpp.h" + +/* internal functions */ + +/* misc */ +char *_lowercase(char *str); + +/* for avl trees */ +int _compare_vars(void *compare_arg, void *a, void *b); +int _free_vars(void *key); + +http_parser_t *httpp_create_parser(void) +{ + return (http_parser_t *)malloc(sizeof(http_parser_t)); +} + +void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) +{ + http_varlist_t *list; + + parser->req_type = httpp_req_none; + parser->uri = NULL; + parser->vars = avl_tree_new(_compare_vars, NULL); + + /* now insert the default variables */ + list = defaults; + while (list != NULL) { + httpp_setvar(parser, list->var.name, list->var.value); + list = list->next; + } +} + +int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len) +{ + char *data, *tmp; + char *line[32]; /* limited to 32 lines, should be more than enough */ + int i, l, retlen; + int lines; + char *req_type; + char *uri; + char *version; + char *name, *value; + int whitespace, where; + int slen; + + if (http_data == NULL) + return 0; + + /* make a local copy of the data */ + data = (char *)malloc(len); + if (data == NULL) return 0; + memcpy(data, http_data, len); + + /* first we count how many lines there are + ** and set up the line[] array + */ + lines = 0; + line[lines] = data; + for (i = 0; i < len; i++) { + if (data[i] == '\r') + data[i] = '\0'; + if (data[i] == '\n') { + lines++; + if (i + 1 < len) + if (data[i + 1] == '\n' || data[i + 1] == '\r') { + data[i] = '\0'; + break; + } + data[i] = '\0'; + if (i < len - 1) + line[lines] = &data[i + 1]; + } + } + + i++; + while (data[i] == '\n') i++; + retlen = i; + + /* parse the first line special + ** the format is: + ** REQ_TYPE URI VERSION + ** eg: + ** GET /index.html HTTP/1.0 + */ + where = 0; + whitespace = 0; + slen = strlen(line[0]); + req_type = line[0]; + for (i = 0; i < slen; i++) { + if (line[0][i] == ' ') { + whitespace = 1; + line[0][i] = '\0'; + } else { + /* we're just past the whitespace boundry */ + if (whitespace) { + whitespace = 0; + where++; + switch (where) { + case 1: + uri = &line[0][i]; + break; + case 2: + version = &line[0][i]; + break; + } + } + } + } + + if (strcasecmp("GET", req_type) == 0) { + parser->req_type = httpp_req_get; + } else if (strcasecmp("POST", req_type) == 0) { + parser->req_type = httpp_req_post; + } else if (strcasecmp("HEAD", req_type) == 0) { + parser->req_type = httpp_req_head; + } else if (strcasecmp("SOURCE", req_type) == 0) { + parser->req_type = httpp_req_source; + } else if (strcasecmp("PLAY", req_type) == 0) { + parser->req_type = httpp_req_play; + } else if (strcasecmp("STATS", req_type) == 0) { + parser->req_type = httpp_req_stats; + } else { + parser->req_type = httpp_req_unknown; + } + + if (uri != NULL && strlen(uri) > 0) + parser->uri = strdup(uri); + else + parser->uri = NULL; + + if ((version != NULL) && ((tmp = strchr(version, '/')) != NULL)) { + tmp[0] = '\0'; + if ((strlen(version) > 0) && (strlen(&tmp[1]) > 0)) { + httpp_setvar(parser, HTTPP_VAR_PROTOCOL, _lowercase(version)); + httpp_setvar(parser, HTTPP_VAR_VERSION, &tmp[1]); + } else { + free(data); + return 0; + } + } else { + free(data); + return 0; + } + + if (parser->req_type != httpp_req_none && parser->req_type != httpp_req_unknown) { + switch (parser->req_type) { + case httpp_req_get: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "get"); + break; + case httpp_req_post: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "post"); + break; + case httpp_req_head: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "head"); + break; + case httpp_req_source: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "source"); + break; + case httpp_req_play: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "play"); + break; + case httpp_req_stats: + httpp_setvar(parser, HTTPP_VAR_REQ_TYPE, "stats"); + break; + default: + break; + } + } else { + free(data); + return 0; + } + + if (parser->uri != NULL) { + httpp_setvar(parser, HTTPP_VAR_URI, parser->uri); + } else { + free(data); + return 0; + } + + /* parse the name: value lines. */ + for (l = 1; l < lines; l++) { + where = 0; + whitespace = 0; + name = line[l]; + value = NULL; + slen = strlen(line[l]); + for (i = 0; i < slen; i++) { + if (line[l][i] == ':') { + whitespace = 1; + line[l][i] = '\0'; + } else { + if (whitespace) { + whitespace = 0; + while (i < slen && line[l][i] == ' ') + i++; + + if (i < slen) + value = &line[l][i]; + + break; + } + } + } + + if (name != NULL && value != NULL) { + httpp_setvar(parser, _lowercase(name), value); + name = NULL; + value = NULL; + } + } + + free(data); + + return retlen; +} + +void httpp_setvar(http_parser_t *parser, char *name, char *value) +{ + http_var_t *var; + + if (name == NULL || value == NULL) + return; + + var = (http_var_t *)malloc(sizeof(http_var_t)); + if (var == NULL) return; + + var->name = strdup(name); + var->value = strdup(value); + + if (httpp_getvar(parser, name) == NULL) { + avl_insert(parser->vars, (void *)var); + } else { + avl_delete(parser->vars, (void *)var, _free_vars); + avl_insert(parser->vars, (void *)var); + } +} + +char *httpp_getvar(http_parser_t *parser, char *name) +{ + http_var_t var; + http_var_t *found; + + var.name = name; + var.value = NULL; + + if (avl_get_by_key(parser->vars, (void *)&var, (void **)&found) == 0) + return found->value; + else + return NULL; +} + +void httpp_destroy(http_parser_t *parser) +{ + parser->req_type = httpp_req_none; + if (parser->uri) + free(parser->uri); + parser->uri = NULL; + avl_tree_free(parser->vars, _free_vars); + parser->vars = NULL; +} + +char *_lowercase(char *str) +{ + long i; + for (i = 0; i < strlen(str); i++) + str[i] = tolower(str[i]); + + return str; +} + +int _compare_vars(void *compare_arg, void *a, void *b) +{ + http_var_t *vara, *varb; + + vara = (http_var_t *)a; + varb = (http_var_t *)b; + + return strcmp(vara->name, varb->name); +} + +int _free_vars(void *key) +{ + http_var_t *var; + + var = (http_var_t *)key; + + if (var->name) + free(var->name); + if (var->value) + free(var->value); + free(var); + + return 1; +} + diff --git a/httpp/httpp.h b/httpp/httpp.h new file mode 100644 index 0000000..a7bddce --- /dev/null +++ b/httpp/httpp.h @@ -0,0 +1,47 @@ +/* httpp.h +** +** http parsing library +*/ + +#ifndef __HTTPP_H +#define __HTTPP_H + +#include "avl.h" + +#define HTTPP_VAR_PROTOCOL "__protocol" +#define HTTPP_VAR_VERSION "__version" +#define HTTPP_VAR_URI "__uri" +#define HTTPP_VAR_REQ_TYPE "__req_type" + +typedef enum httpp_request_type_tag { + httpp_req_none, httpp_req_get, httpp_req_post, httpp_req_head, httpp_req_source, httpp_req_play, httpp_req_stats, httpp_req_unknown +} httpp_request_type_e; + +typedef struct http_var_tag { + char *name; + char *value; +} http_var_t; + +typedef struct http_varlist_tag { + http_var_t var; + struct http_varlist_tag *next; +} http_varlist_t; + +typedef struct http_parser_tag { + httpp_request_type_e req_type; + char *uri; + + avl_tree *vars; +} http_parser_t; + +http_parser_t *httpp_create_parser(void); +void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults); +int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len); +void httpp_setvar(http_parser_t *parser, char *name, char *value); +char *httpp_getvar(http_parser_t *parser, char *name); +void httpp_destroy(http_parser_t *parser); + +#endif + + + diff --git a/httpp/test.c b/httpp/test.c new file mode 100644 index 0000000..ee0f61c --- /dev/null +++ b/httpp/test.c @@ -0,0 +1,59 @@ +#include + +#include +#include "httpp.h" + + +int main(int argc, char **argv) +{ + char buff[8192]; + int readed; + http_parser_t parser; + avl_node *node; + http_var_t *var; + + httpp_initialize(&parser, NULL); + + readed = fread(buff, 1, 8192, stdin); + if (httpp_parse(&parser, buff, readed)) { + printf("Parse succeeded...\n\n"); + printf("Request was "); + switch (parser.req_type) { + case httpp_req_none: + printf(" none\n"); + break; + case httpp_req_unknown: + printf(" unknown\n"); + break; + case httpp_req_get: + printf(" get\n"); + break; + case httpp_req_post: + printf(" post\n"); + break; + case httpp_req_head: + printf(" head\n"); + break; + } + printf("Version was 1.%d\n", parser.version); + + node = avl_get_first(parser.vars); + while (node) { + var = (http_var_t *)node->key; + + if (var) + printf("Iterating variable(s): %s = %s\n", var->name, var->value); + + node = avl_get_next(node); + } + } else { + printf("Parse failed...\n"); + } + + printf("Destroying parser...\n"); + httpp_destroy(&parser); + + return 0; +} + + diff --git a/log/Makefile.am b/log/Makefile.am new file mode 100644 index 0000000..d169e73 --- /dev/null +++ b/log/Makefile.am @@ -0,0 +1,18 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libicelog.la +noinst_HEADERS = log.h + +libicelog_la_SOURCES = log.c + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/log/log.c b/log/log.c new file mode 100644 index 0000000..512c192 --- /dev/null +++ b/log/log.c @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#else +#include +#endif + +#include "log.h" + +#define LOG_MAXLOGS 25 +#define LOG_MAXLINELEN 1024 + +#ifdef _WIN32 +#define mutex_t CRITICAL_SECTION +#else +#define mutex_t pthread_mutex_t +#endif + +static mutex_t _logger_mutex; +static int _initialized = 0; + +typedef struct log_tag +{ + int in_use; + + int level; + + char *filename; + FILE *logfile; + + char *buffer; +} log_t; + +log_t loglist[LOG_MAXLOGS]; + +int _get_log_id(); +void _release_log_id(int log_id); +static void _lock_logger(); +static void _unlock_logger(); + +void log_initialize() +{ + int i; + + if (_initialized) return; + + for (i = 0; i < LOG_MAXLOGS; i++) { + loglist[i].in_use = 0; + loglist[i].level = 2; + loglist[i].filename = NULL; + loglist[i].logfile = NULL; + loglist[i].buffer = NULL; + } + + /* initialize mutexes */ +#ifndef _WIN32 + pthread_mutex_init(&_logger_mutex, NULL); +#else + InitializeCriticalSection(&_logger_mutex); +#endif + + _initialized = 1; +} + +int log_open(const char *filename) +{ + int log_id; + + if (filename == NULL) return LOG_EINSANE; + if (strcmp(filename, "") == 0) return LOG_EINSANE; + + log_id = _get_log_id(); + if (log_id < 0) return LOG_ENOMORELOGS; + + loglist[log_id].logfile = fopen(filename, "a"); + if (loglist[log_id].logfile != NULL) { + loglist[log_id].filename = (char *)strdup(filename); + } else { + _release_log_id(log_id); + return LOG_ECANTOPEN; + } + + return log_id; +} + +int log_open_with_buffer(const char *filename, int size) +{ + /* not implemented */ + return 0; +} + +void log_set_level(int log_id, int level) +{ + if (log_id < 0 || log_id >= LOG_MAXLOGS) return; + if (loglist[log_id].in_use == 0) return; + + loglist[log_id].level = level; +} + +void log_flush(int log_id) +{ + if (log_id < 0 || log_id >= LOG_MAXLOGS) return; + if (loglist[log_id].in_use == 0) return; + + fflush(loglist[log_id].logfile); +} + +void log_reopen(int log_id) +{ + /* not implemented yet */ +} + +void log_close(int log_id) +{ + if (log_id < 0 || log_id >= LOG_MAXLOGS) return; + if (loglist[log_id].in_use == 0) return; + + loglist[log_id].in_use = 0; + loglist[log_id].level = 2; + if (loglist[log_id].filename) free(loglist[log_id].filename); + if (loglist[log_id].buffer) free(loglist[log_id].buffer); + fclose(loglist[log_id].logfile); + loglist[log_id].logfile = NULL; +} + +void log_shutdown() +{ + /* destroy mutexes */ +#ifndef _WIN32 + pthread_mutex_destroy(&_logger_mutex); +#else + DeleteCriticalSection(&_logger_mutex); +#endif + + _initialized = 0; +} + +void log_write(int log_id, int priority, const char *cat, const char *fmt, ...) +{ + static char prior[4][5] = { "EROR\0", "WARN\0", "INFO\0", "DBUG\0" }; + char tyme[128]; + char pre[256]; + char line[LOG_MAXLINELEN]; + time_t now; + va_list ap; + + if (log_id < 0) return; + if (loglist[log_id].level < priority) return; + + + va_start(ap, fmt); + vsnprintf(line, LOG_MAXLINELEN, fmt, ap); + + now = time(NULL); + strftime(tyme, 128, "[%Y-%m-%d %H:%M:%S]", gmtime(&now)); + + snprintf(pre, 256, "%s %s", prior[priority-1], cat); + + fprintf(loglist[log_id].logfile, "%s %s %s\n", tyme, pre, line); + + va_end(ap); +} + +void log_write_direct(int log_id, const char *fmt, ...) +{ + char line[LOG_MAXLINELEN]; + va_list ap; + + if (log_id < 0) return; + + va_start(ap, fmt); + vsnprintf(line, LOG_MAXLINELEN, fmt, ap); + fprintf(loglist[log_id].logfile, "%s\n", line); + va_end(ap); + + fflush(loglist[log_id].logfile); +} + +int _get_log_id() +{ + int i; + int id = -1; + + /* lock mutex */ + _lock_logger(); + + for (i = 0; i < LOG_MAXLOGS; i++) + if (loglist[i].in_use == 0) { + loglist[i].in_use = 1; + id = i; + break; + } + + /* unlock mutex */ + _unlock_logger(); + + return id; +} + +void _release_log_id(int log_id) +{ + /* lock mutex */ + _lock_logger(); + + loglist[log_id].in_use = 0; + + /* unlock mutex */ + _unlock_logger(); +} + +static void _lock_logger() +{ +#ifndef _WIN32 + pthread_mutex_lock(&_logger_mutex); +#else + EnterCriticalSection(&_logger_mutex); +#endif +} + +static void _unlock_logger() +{ +#ifndef _WIN32 + pthread_mutex_unlock(&_logger_mutex); +#else + LeaveCriticalSection(&_logger_mutex); +#endif +} + + + + diff --git a/log/log.h b/log/log.h new file mode 100644 index 0000000..0b061cb --- /dev/null +++ b/log/log.h @@ -0,0 +1,22 @@ +#ifndef __LOG_H__ +#define __LOG_H__ + +#define LOG_EINSANE -1 +#define LOG_ENOMORELOGS -2 +#define LOG_ECANTOPEN -3 +#define LOG_ENOTOPEN -4 + + +void log_initialize(); +int log_open(const char *filename); +int log_open_with_buffer(const char *filename, int size); +void log_set_level(int log_id, int level); +void log_flush(int log_id); +void log_reopen(int log_id); +void log_close(int log_id); +void log_shutdown(); + +void log_write(int log_id, int priority, const char *cat, const char *fmt, ...); +void log_write_direct(int log_id, const char *fmt, ...); + +#endif /* __LOG_H__ */ diff --git a/log/test.c b/log/test.c new file mode 100644 index 0000000..773c1b7 --- /dev/null +++ b/log/test.c @@ -0,0 +1,21 @@ +#include "log.h" + +#define CATMODULE "test" + +#define LOG_ERR(x, y, z...) log_write(x, 1, CATMODULE "/" __FUNCTION__, y, ##z) + + +int main(void) +{ + int lid; + + log_initialize(); + + lid = log_open("test.log"); + + LOG_ERR(lid, "The log id is %d, damnit...", lid); + + log_close(lid); + + log_shutdown(); +} diff --git a/net/BUILDING b/net/BUILDING new file mode 100644 index 0000000..b63563a --- /dev/null +++ b/net/BUILDING @@ -0,0 +1,3 @@ +defines that affect compilation + +none currently diff --git a/net/COPYING b/net/COPYING new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/net/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/net/Makefile.am b/net/Makefile.am new file mode 100644 index 0000000..d87a910 --- /dev/null +++ b/net/Makefile.am @@ -0,0 +1,18 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libicenet.la +noinst_HEADERS = resolver.h sock.h + +libicenet_la_SOURCES = sock.c resolver.c + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/net/README b/net/README new file mode 100644 index 0000000..d0d2d00 --- /dev/null +++ b/net/README @@ -0,0 +1,10 @@ +This is a name resolving library that's threadsafe. + +Right now it only implements this with mutexes, but we should extend it to use gethostbyXXXX_r() +if it's available. + +It shoudl work on win32, but i'm probably forgetting a headerfile. + +API is basically not going to change. Please consult with the rest of the team before changing the interface. + +jack. \ No newline at end of file diff --git a/net/TODO b/net/TODO new file mode 100644 index 0000000..3357459 --- /dev/null +++ b/net/TODO @@ -0,0 +1 @@ +- add getXbyY_r function support diff --git a/net/resolver.c b/net/resolver.c new file mode 100644 index 0000000..e2d865d --- /dev/null +++ b/net/resolver.c @@ -0,0 +1,182 @@ +/* +** resolver.c +** +** name resolver library +** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "resolver.h" +#include "sock.h" + +/* internal function */ + +static void _lock_resolver(void); +static void _unlock_resolver(void); +static char *_lookup(const char *what, char *buff, int len); +static int _isip(const char *what); + +/* internal data */ + +#ifdef _WIN32 +#define mutex_t CRITICAL_SECTION +#else +#define mutex_t pthread_mutex_t +#endif + +static mutex_t _resolver_mutex; +static int _initialized = 0; + +char *resolver_getname(const char *ip, char *buff, int len) +{ + if (!_isip(ip)) { + strncpy(buff, ip, len); + return buff; + } + + return _lookup(ip, buff, len); +} + +char *resolver_getip(const char *name, char *buff, int len) +{ + if (_isip(name)) { + strncpy(buff, name, len); + return buff; + } + + return _lookup(name, buff, len); +} + +static int _isip(const char *what) +{ +#ifdef HAVE_IPV6 + union { + struct in_addr v4addr; + struct in6_addr v6addr; + } addr_u; + + if (inet_pton(AF_INET, what, &addr_u.v4addr) <= 0) + return inet_pton(AF_INET6, what, &addr_u.v6addr) > 0 ? 1 : 0; + + return 1; +#else + struct in_addr inp; + + return inet_aton(what, &inp); +#endif +} + +static char *_lookup(const char *what, char *buff, int len) +{ + /* linux doesn't appear to have getipnodebyname as of glibc-2.2.3, so the IPV6 lookup is untested */ +#ifdef HAVE_GETIPNODEBYNAME + int err; +#else + struct in_addr inp; +#endif + struct hostent *host = NULL; + char *temp; + + /* do a little sanity checking */ + if (what == NULL || buff == NULL || len <= 0) + return NULL; + +#ifdef HAVE_GETIPNODEBYNAME + host = getipnodebyname(what, AF_INET6, AI_DEFAULT, &err); + if (host) { + if (_isip(what)) + strncpy(buff, host->h_name, len); + else + inet_ntop(host->h_addrtype, host->h_addr_list[0], buff, len); + + freehostent(host); + } else + buff = NULL; +#else + if (_isip(what)) { + /* gotta lock calls for now, since gethostbyname and such + * aren't threadsafe */ + _lock_resolver(); + host = gethostbyaddr((char *)&inp, sizeof(struct in_addr), AF_INET); + _unlock_resolver(); + if (host == NULL) { + buff = NULL; + } else { + strncpy(buff, host->h_name, len); + } + } else { + _lock_resolver(); + host = gethostbyname(what); + _unlock_resolver(); + + if (host == NULL) { + buff = NULL; + } else { + temp = inet_ntoa(*(struct in_addr *)host->h_addr); + strncpy(buff, temp, len); + } + } + +#endif + return buff; +} + +void resolver_initialize() +{ + /* initialize the lib if we havne't done so already */ + + if (!_initialized) { + _initialized = 1; +#ifndef _WIN32 + pthread_mutex_init(&_resolver_mutex, NULL); +#else + InitializeCriticalSection(&_resolver_mutex); +#endif + + /* keep dns connects (TCP) open */ + sethostent(1); + } +} + +void resolver_shutdown(void) +{ + if (_initialized) { +#ifndef _WIN32 + pthread_mutex_destroy(&_resolver_mutex); +#else + DestroyCriticalSection(&_resolver_mutex); +#endif + + _initialized = 0; + } +} + +static void _lock_resolver() +{ +#ifndef _WIN32 + pthread_mutex_lock(&_resolver_mutex); +#else + EnterCriticalSection(&_resolver_mutex); +#endif +} + +static void _unlock_resolver() +{ +#ifndef _WIN32 + pthread_mutex_unlock(&_resolver_mutex); +#else + LeaveCriticalSection(&_resolver_mutex); +#endif +} diff --git a/net/resolver.h b/net/resolver.h new file mode 100644 index 0000000..a901754 --- /dev/null +++ b/net/resolver.h @@ -0,0 +1,34 @@ +/* +** resolver.h +** +** name resolver library header +** +*/ + +#ifndef __RESOLVER_H +#define __RESOLVER_H + + +/* +** resolver_lookup +** +** resolves a hosts name from it's ip address +** or +** resolves an ip address from it's host name +** +** returns a pointer to buff, or NULL if an error occured +** +*/ + +void resolver_initialize(void); +void resolver_shutdown(void); + +char *resolver_getname(const char *ip, char *buff, int len); +char *resolver_getip(const char *name, char *buff, int len); + +#endif + + + + + diff --git a/net/sock.c b/net/sock.c new file mode 100644 index 0000000..e629243 --- /dev/null +++ b/net/sock.c @@ -0,0 +1,511 @@ +/* sock.c + * - General Socket Functions + * + * Copyright (c) 1999 the icecast team + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#else +#include +#define vsnprintf _vsnprintf +#define EINPROGRESS WSAEINPROGRESS +#define ENOTSOCK WSAENOTSOCK +#endif + +#include "sock.h" +#include "resolver.h" + +#ifndef _WIN32 +extern int errno; +#endif + +/* sock_initialize +** +** initializes the socket library. you must call this +** before using the library! +*/ +void sock_initialize(void) +{ +#ifdef _WIN32 + WSADATA wsad; + WSAStartup(0x0101, &wsad); +#endif + + resolver_initialize(); +} + +/* sock_shutdown +** +** shutdown the socket library. remember to call this when you're +** through using the lib +*/ +void sock_shutdown(void) +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} + +/* sock_get_localip +** +** gets the local ip address for the machine +** the ip it returns *should* be on the internet. +** in any case, it's as close as we can hope to get +** unless someone has better ideas on how to do this +*/ +char *sock_get_localip(char *buff, int len) +{ + char temp[1024]; + + if (gethostname(temp, 1024) != 0) + return NULL; + + if (resolver_getip(temp, buff, len)) + return buff; + + return NULL; +} + +/* sock_error +** +** returns the last socket error +*/ +int sock_error(void) +{ +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +} + +/* sock_recoverable +** +** determines if the socket error is recoverable +** in terms of non blocking sockets +*/ +int sock_recoverable(int error) +{ + return (error == EAGAIN || error == EINTR || error == EINPROGRESS || error == EWOULDBLOCK); +} + +/* sock_valid_socket +** +** determines if a sock_t represents a valid socket +*/ +int sock_valid_socket(sock_t sock) +{ + int ret; + int optval, optlen; + + optlen = sizeof(int); + ret = getsockopt(sock, SOL_SOCKET, SO_TYPE, &optval, &optlen); + + return (ret == 0); +} + +/* inet_aton +** +** turns an ascii ip address into a binary representation +*/ +#ifdef _WIN32 +int inet_aton(const char *s, struct in_addr *a) +{ + int lsb, b2, b3, msb; + + if (sscanf(s, "%d.%d.%d.%d", &lsb, &b2, &b3, &msb) < 4) { + return 0; + } + + a->s_addr = inet_addr(s); + + return (a->s_addr != INADDR_NONE); +} +#endif /* _WIN32 */ + +/* sock_set_blocking +** +** set the sock blocking or nonblocking +** SOCK_BLOCK for blocking +** SOCK_NONBLOCK for nonblocking +*/ +int sock_set_blocking(sock_t sock, const int block) +{ +#ifdef _WIN32 + int varblock = block; +#endif + + if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1)) + return SOCK_ERROR; + +#ifdef _WIN32 + return ioctlsocket(sock, FIONBIO, &varblock); +#else + return fcntl(sock, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK); +#endif +} + +/* sock_close +** +** close the socket +*/ +int sock_close(sock_t sock) +{ +#ifdef _WIN32 + return closesocket(sock); +#else + return close(sock); +#endif +} + +/* sock_write_bytes +** +** write bytes to the socket +** this function will block until all bytes are +** written, or there is an unrecoverable error +** even if the socket is non-blocking +*/ +int sock_write_bytes(sock_t sock, const char *buff, const int len) +{ +// int wrote, res, polled; + int res; +// struct pollfd socks; + + /* sanity check */ + if (!buff) { + return SOCK_ERROR; + } else if (len <= 0) { + return SOCK_ERROR; + } else if (!sock_valid_socket(sock)) { + return SOCK_ERROR; + } + +// socks.fd = sock; +// socks.events = POLLOUT; + +// wrote = 0; +// while (wrote < len) { +// polled = poll(&socks, 1, 30000); + +// if ((polled == -1) && sock_recoverable(sock_error())) +// continue; +// if (polled != 1) +// return SOCK_ERROR; + +// res = send(sock, &buff[wrote], len - wrote, 0); + res = send(sock, buff, len, 0); +// +// if ((res < 0) && (!sock_recoverable(sock_error()))) +// return SOCK_ERROR; +// if (res > 0) +// wrote += res; +// } +// +// return wrote; + + return res; +} + +/* sock_write_string +** +** writes a string to a socket +** this function always blocks even if the socket is nonblocking +*/ +int sock_write_string(sock_t sock, const char *buff) +{ + return (sock_write_bytes(sock, buff, strlen(buff)) > 0); +} + +/* sock_write +** +** write a formatted string to the socket +** this function will always block, even if the socket is nonblocking +** will truncate the string if it's greater than 1024 chars. +*/ +int sock_write(sock_t sock, const char *fmt, ...) +{ + char buff[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buff, 1024, fmt, ap); + va_end(ap); + + return sock_write_bytes(sock, buff, strlen(buff)); +} + +int sock_read_bytes(sock_t sock, char *buff, const int len) +{ +// int ret; + + if (!sock_valid_socket(sock)) return 0; + if (!buff) return 0; + if (len <= 0) return 0; + + return recv(sock, buff, len, 0); +} + +/* sock_read_line +** +** Read one line of at max len bytes from sock into buff. +** If ok, return 1 and nullterminate buff. Otherwize return 0. +** Terminating \n is not put into the buffer. +** +** this function will probably not work on sockets in nonblocking mode +*/ +int sock_read_line(sock_t sock, char *buff, const int len) +{ + char c = '\0'; + int read_bytes, pos; + + if (!sock_valid_socket(sock)) { + return 0; + } else if (!buff) { + return 0; + } else if (len <= 0) { + return 0; + } + + pos = 0; + read_bytes = recv(sock, &c, 1, 0); + + if (read_bytes < 0) { + return 0; + } + + while ((c != '\n') && (pos < len) && (read_bytes == 1)) { + if (c != '\r') + buff[pos++] = c; + read_bytes = recv(sock, &c, 1, 0); + } + + if (read_bytes == 1) { + buff[pos] = '\0'; + return 1; + } else { + return 0; + } +} + +/* sock_connect_wto +** +** Connect to hostname on specified port and return the created socket. +** timeout specifies the maximum time to wait for this to finish and +** returns when it expires whether it connected or not +** setting timeout to 0 disable the timeout. +*/ +sock_t sock_connect_wto(const char *hostname, const int port, const int timeout) +{ + sock_t sock; + struct sockaddr_in sin, server; + char ip[20]; + + if (!hostname || !hostname[0]) { + return SOCK_ERROR; + } else if (port <= 0) { + return SOCK_ERROR; + } + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == SOCK_ERROR) { + sock_close(sock); + return SOCK_ERROR; + } + + memset(&sin, 0, sizeof(struct sockaddr_in)); + memset(&server, 0, sizeof(struct sockaddr_in)); + + if (!resolver_getip(hostname, ip, 20)) + return SOCK_ERROR; + + if (inet_aton(ip, (struct in_addr *)&sin.sin_addr) == 0) { + sock_close(sock); + return SOCK_ERROR; + } + + memcpy(&server.sin_addr, &sin.sin_addr, sizeof(struct sockaddr_in)); + + server.sin_family = AF_INET; + server.sin_port = htons(port); + + /* if we have a timeout, use select, if not, use connect straight. */ + /* dunno if this is portable, and it sure is complicated for such a + simple thing to want to do. damn BSD sockets! */ + if (timeout > 0) { + fd_set wfds; + struct timeval tv; + int retval; + int val; + int valsize = sizeof(int); + + FD_ZERO(&wfds); + FD_SET(sock, &wfds); + tv.tv_sec = timeout; + tv.tv_usec = 0; + + sock_set_blocking(sock, SOCK_NONBLOCK); + retval = connect(sock, (struct sockaddr *)&server, sizeof(server)); + if (retval == 0) { + sock_set_blocking(sock, SOCK_BLOCK); + return sock; + } else { + if (!sock_recoverable(sock_error())) { + sock_close(sock); + return SOCK_ERROR; + } + } + + if (select(sock + 1, NULL, &wfds, NULL, &tv)) { + retval = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&val, (int *)&valsize); + if ((retval == 0) && (val == 0)) { + sock_set_blocking(sock, SOCK_BLOCK); + return sock; + } else { + sock_close(sock); + return SOCK_ERROR; + } + } else { + sock_close(sock); + return SOCK_ERROR; + } + } else { + if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == 0) { + return sock; + } else { + sock_close(sock); + return SOCK_ERROR; + } + } +} + +/* sock_get_server_socket +** +** create a socket for incoming requests on a specified port and +** interface. if interface is null, listen on all interfaces. +** returns the socket, or SOCK_ERROR on failure +*/ +sock_t sock_get_server_socket(const int port, char *interface) +{ +#ifdef HAVE_IPV6 + struct sockaddr_storage sa; +#else + struct sockaddr_in sa; +#endif + int sa_family, sa_len, error, opt; + sock_t sock; + char ip[40]; + + if (port < 0) + return SOCK_ERROR; + + /* defaults */ + memset(&sa, 0, sizeof(sa)); + sa_family = AF_INET; + sa_len = sizeof (struct sockaddr_in); + + /* set the interface to bind to if specified */ + if (interface != NULL) { + if (!resolver_getip(interface, ip, sizeof (ip))) + return SOCK_ERROR; + +#ifdef HAVE_IPV6 + if (inet_pton(AF_INET, ip, &((struct sockaddr_in*)&sa)->sin_addr) > 0) { + ((struct sockaddr_in*)&sa)->sin_family = AF_INET; + ((struct sockaddr_in*)&sa)->sin_port = htons(port); + } else if (inet_pton(AF_INET6, ip, &((struct sockaddr_in6*)&sa)->sin6_addr) > 0) { + sa_family = AF_INET6; + sa_len = sizeof (struct sockaddr_in6); + ((struct sockaddr_in6*)&sa)->sin6_family = AF_INET6; + ((struct sockaddr_in6*)&sa)->sin6_port = htons(port); + } else + return SOCK_ERROR; +#else + if (!inet_aton(ip, &sa.sin_addr)) + return SOCK_ERROR; + else { + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + } +#endif + } else { + ((struct sockaddr_in*)&sa)->sin_addr.s_addr = INADDR_ANY; + ((struct sockaddr_in*)&sa)->sin_family = AF_INET; + ((struct sockaddr_in*)&sa)->sin_port = htons(port); + } + + /* get a socket */ + sock = socket(sa_family, SOCK_STREAM, 0); + if (sock == -1) + return SOCK_ERROR; + + /* reuse it if we can */ + opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int)); + + /* bind socket to port */ + error = bind(sock, (struct sockaddr *)&sa, sa_len); + if (error == -1) + return SOCK_ERROR; + + return sock; +} + +int sock_listen(sock_t serversock, int backlog) +{ + if (!sock_valid_socket(serversock)) + return 0; + + if (backlog <= 0) + backlog = 10; + + return (listen(serversock, backlog) == 0); +} + +int sock_accept(sock_t serversock, char *ip, int len) +{ + struct sockaddr_in sin; + int ret; + int slen; + + if (!sock_valid_socket(serversock)) + return SOCK_ERROR; + + slen = sizeof(struct sockaddr_in); + ret = accept(serversock, (struct sockaddr *)&sin, &slen); + + if (ret >= 0 && ip != NULL) + strncpy(ip, inet_ntoa(sin.sin_addr), len); + + return ret; +} diff --git a/net/sock.h b/net/sock.h new file mode 100644 index 0000000..8e458dc --- /dev/null +++ b/net/sock.h @@ -0,0 +1,75 @@ +/* sock.h + * - General Socket Function Headers + * + * Copyright (c) 1999 the icecast team + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __SOCK_H +#define __SOCK_H + +#ifdef _WIN32 +#include +typedef SOCKET sock_t +#else +typedef int sock_t; +#endif + +#define SOCK_ERROR -1 +#define SOCK_BLOCK 0 +#define SOCK_NONBLOCK 1 + +/* sock connect macro */ +#define sock_connect(h, p) sock_connect_wto(h, p, 0) + +/* Misc socket functions */ +void sock_initialize(void); +void sock_shutdown(void); +char *sock_get_localip(char *buff, int len); +int sock_error(void); +int sock_recoverable(int error); +int sock_valid_socket(sock_t sock); +int sock_set_blocking(sock_t sock, const int block); +int sock_close(sock_t sock); + +/* Connection related socket functions */ +sock_t sock_connect_wto(const char *hostname, const int port, const int timeout); + +/* Socket write functions */ +int sock_write_bytes(sock_t sock, const char *buff, const int len); +int sock_write(sock_t sock, const char *fmt, ...); +int sock_write_string(sock_t sock, const char *buff); + +/* Socket read functions */ +int sock_read_bytes(sock_t sock, char *buff, const int len); +int sock_read_line(sock_t sock, char *string, const int len); + +/* server socket functions */ +sock_t sock_get_server_socket(const int port, char *interface); +int sock_listen(sock_t serversock, int backlog); +int sock_accept(sock_t serversock, char *ip, int len); + +#ifdef _WIN32 +int inet_aton(const char *s, struct in_addr *a); +#endif + +#endif /* __SOCK_H */ + + + + + diff --git a/net/test_resolver.c b/net/test_resolver.c new file mode 100644 index 0000000..9991956 --- /dev/null +++ b/net/test_resolver.c @@ -0,0 +1,17 @@ +#include +#include + +#include "resolver.h" + +int main() +{ + char buff[1024]; + + resolver_initialize(); + + printf("I got %s, when looking up %s.\n", resolver_getip("bach.greenwitch.com", buff, 1024), "bach.greenwitch.com"); + printf("I got %s, when looking up %s.\n", resolver_getname("207.181.249.14", buff, 1024), "207.181.249.14"); + + return 0; +} + diff --git a/thread/BUILDING b/thread/BUILDING new file mode 100644 index 0000000..ebe8422 --- /dev/null +++ b/thread/BUILDING @@ -0,0 +1,20 @@ +defines that affect compilation + +_WIN32 + this should be defined for Win32 platforms + +DEBUG_MUTEXES + define this to turn on mutex debugging. this will log locks/unlocks. + +CHECK_MUTEXES (DEBUG_MUTEXES must also be defined) + checks to make sure mutex operations make sense. ie, multi_mutex is locked + when locking multiple mutexes, etc. + +THREAD_DEBUG (define to 1-4) + turns on the thread.log logging + + + + + + diff --git a/thread/COPYING b/thread/COPYING new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/thread/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/thread/Makefile.am b/thread/Makefile.am new file mode 100644 index 0000000..e8cff54 --- /dev/null +++ b/thread/Makefile.am @@ -0,0 +1,20 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libicethread.la +noinst_HEADERS = thread.h + +libicethread_la_SOURCES = thread.c + +INCLUDES = -I$(srcdir)/../avl -I$(srcdir)/../log + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/thread/README b/thread/README new file mode 100644 index 0000000..0ccadb0 --- /dev/null +++ b/thread/README @@ -0,0 +1,9 @@ +This is the cross platform thread and syncronization library. + +It depends on the avl library. + +This is a massively cleaned and picked through version of the code from +the icecast 1.3.x base. It has not been heavily tested *YET*. But since +it's just cleanups, it really shouldn't have that many problems. + +jack. diff --git a/thread/TODO b/thread/TODO new file mode 100644 index 0000000..84f2010 --- /dev/null +++ b/thread/TODO @@ -0,0 +1,5 @@ +- make DEBUG_MUTEXES and CHECK_MUTEXES work + +- recursive locking/unlocking (easy) +- reader/writer locking (easy) +- make a mode were _log is disabled (normal mode) (easy) diff --git a/thread/thread.c b/thread/thread.c new file mode 100644 index 0000000..3b6053e --- /dev/null +++ b/thread/thread.c @@ -0,0 +1,733 @@ +/* threads.c +** - Thread Abstraction Functions +** +** Copyright (c) 1999, 2000 the icecast team +** +** 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 latfer 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include + +#include + +#include "log.h" +#include "thread.h" +#include "avl.h" + +#define CATMODULE "thread" +#define LOG_ERROR(y, z...) log_write(_logid, 1, CATMODULE "/" __FUNCTION__, y, ##z) +#define LOG_WARN(y, z...) log_write(_logid, 2, CATMODULE "/" __FUNCTION__, y, ##z) +#define LOG_INFO(y, z...) log_write(_logid, 3, CATMODULE "/" __FUNCTION__, y, ##z) +#define LOG_DEBUG(y, z...) log_write(_logid, 4, CATMODULE "/" __FUNCTION__, y, ##z) + +/* INTERNAL DATA */ +#define STACKSIZE 8192 + +/* thread starting structure */ +typedef struct thread_start_tag { + /* the real start routine and arg */ + void *(*start_routine)(void *); + void *arg; + + /* whether to create the threaded in detached state */ + int detached; + + /* the other stuff we need to make sure this thread is inserted into + ** the thread tree + */ + thread_t *thread; + pthread_t sys_thread; +} thread_start_t; + +static int _logid = -1; +static long _next_thread_id = 0; +static int _initialized = 0; +static avl_tree *_threadtree = NULL; +static mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; + +static long _next_mutex_id = 0; +static avl_tree *_mutextree = NULL; +static mutex_t _mutextree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; +static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; + +/* INTERNAL FUNCTIONS */ + +/* avl tree functions */ +static int _compare_mutexes(void *compare_arg, void *a, void *b); +static int _compare_threads(void *compare_arg, void *a, void *b); +static int _free_mutex(void *key); +static int _free_thread(void *key); + +/* mutex fuctions */ +static void _mutex_create(mutex_t *mutex); +static void _mutex_lock(mutex_t *mutex); +static void _mutex_unlock(mutex_t *mutex); + +/* misc thread stuff */ +static void *_start_routine(void *arg); +static void _catch_signals(void); +static void _block_signals(void); + +/* LIBRARY INITIALIZATION */ + +void thread_initialize(void) +{ + thread_t *thread; + + /* set up logging */ + + log_initialize(); + +#ifdef THREAD_DEBUG + _logid = log_open("thread.log"); + log_set_level(_logid, THREAD_DEBUG); +#endif + + /* create all the interal mutexes, and initialize the mutex tree */ + + _mutextree = avl_tree_new(_compare_mutexes, NULL); + + /* we have to create this one by hand, because there's no + ** mutextree_mutex to lock yet! + */ + _mutex_create(&_mutextree_mutex); + +#ifdef DEBUG_MUTEXES + _mutextree_mutex.mutex_id = _next_mutex_id++; + avl_insert(_mutextree, (void *)&_mutextree_mutex); +#endif + + thread_mutex_create(&_threadtree_mutex); + thread_mutex_create(&_library_mutex); + + /* initialize the thread tree and insert the main thread */ + + _threadtree = avl_tree_new(_compare_threads, NULL); + + thread = (thread_t *)malloc(sizeof(thread_t)); + + thread->thread_id = _next_thread_id++; + thread->line = 0; + thread->file = strdup("main.c"); + thread->sys_thread = pthread_self(); + thread->create_time = time(NULL); + thread->name = strdup("Main Thread"); + + avl_insert(_threadtree, (void *)thread); + + _catch_signals(); + + _initialized = 1; +} + +void thread_shutdown(void) +{ + if (_initialized == 1) { + thread_mutex_destroy(&_library_mutex); + thread_mutex_destroy(&_threadtree_mutex); + thread_mutex_destroy(&_mutextree_mutex); + + avl_tree_free(_mutextree, _free_mutex); + avl_tree_free(_threadtree, _free_thread); + } + +#ifdef THREAD_DEBUG + log_close(_logid); +#endif + + log_shutdown(); +} + +/* + * Signals should be handled by the main thread, nowhere else. + * I'm using POSIX signal interface here, until someone tells me + * that I should use signal/sigset instead + * + * This function only valid for non-Win32 + */ +static void _block_signals(void) +{ +#ifndef _WIN32 + sigset_t ss; + + sigfillset(&ss); + + /* These ones we want */ + sigdelset(&ss, SIGKILL); + sigdelset(&ss, SIGSTOP); + sigdelset(&ss, SIGTERM); + sigdelset(&ss, SIGSEGV); + sigdelset(&ss, SIGBUS); + if (pthread_sigmask(SIG_BLOCK, &ss, NULL) != 0) + LOG_ERROR("Pthread_sigmask() failed for blocking signals"); +#endif +} + +/* + * Let the calling thread catch all the relevant signals + * + * This function only valid for non-Win32 + */ +static void _catch_signals(void) +{ +#ifndef _WIN32 + sigset_t ss; + + sigemptyset(&ss); + + /* These ones should only be accepted by the signal handling thread (main thread) */ + sigaddset(&ss, SIGHUP); + sigaddset(&ss, SIGCHLD); + sigaddset(&ss, SIGINT); + sigaddset(&ss, SIGPIPE); + + if (pthread_sigmask(SIG_UNBLOCK, &ss, NULL) != 0) + LOG_ERROR("pthread_sigmask() failed for catching signals!"); +#endif +} + + +long thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file) +{ + pthread_attr_t attr; + int created; + thread_t *thread; + thread_start_t *start; + + thread = (thread_t *)malloc(sizeof(thread_t)); + start = (thread_start_t *)malloc(sizeof(thread_start_t)); + thread->line = line; + thread->file = strdup(file); + + _mutex_lock(&_threadtree_mutex); + thread->thread_id = _next_thread_id++; + _mutex_unlock(&_threadtree_mutex); + + thread->name = strdup(name); + thread->create_time = time(NULL); + + start->start_routine = start_routine; + start->arg = arg; + start->thread = thread; + start->detached = detached; + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, STACKSIZE); + + created = 0; + if (pthread_create(&thread->sys_thread, &attr, _start_routine, start) == 0) + created = 1; + else + LOG_ERROR("Could not create new thread"); + + pthread_attr_destroy(&attr); + + if (created == 0) { + LOG_ERROR("System won't let me create more threads, giving up"); + return -1; + } + +// return thread->thread_id; + return thread->sys_thread; +} + +/* _mutex_create +** +** creates a mutex +*/ +static void _mutex_create(mutex_t *mutex) +{ + mutex->thread_id = MUTEX_STATE_NEVERLOCKED; + mutex->line = -1; + + pthread_mutex_init(&mutex->sys_mutex, NULL); +} + +void thread_mutex_create_c(mutex_t *mutex, int line, char *file) +{ + _mutex_create(mutex); + +#ifdef DEBUG_MUTEXES + _mutex_lock(&_mutextree_mutex); + mutex->mutex_id = _next_mutex_id++; + avl_insert(_mutextree, (void *)mutex); + _mutex_unlock(&_mutextree_mutex); +#endif +} + +void thread_mutex_destroy (mutex_t *mutex) +{ + pthread_mutex_destroy(&mutex->sys_mutex); + +#ifdef DEBUG_MUTEXES + _mutex_lock(&_mutextree_mutex); + avl_delete(_mutextree, mutex, _free_mutex); + _mutex_unlock(&_mutextree_mutex); +#endif +} + +void thread_mutex_lock_c(mutex_t *mutex, int line, char *file) +{ +#ifdef DEBUG_MUTEXES + thread_t *th = thread_self(); + + if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line); + + LOG_DEBUG("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); + +# ifdef CHECK_MUTEXES + /* Just a little sanity checking to make sure that we're locking + ** mutexes correctly + */ + + if (th) { + int locks = 0; + avl_node *node; + mutex_t *tmutex; + + _mutex_lock(&_mutextree_mutex); + + node = avl_get_first (_mutextree); + + while (node) { + tmutex = (mutex_t *)node->key; + + if (tmutex->mutex_id == mutex->mutex_id) { + if (tmutex->thread_id == th->thread_id) { + /* Deadlock, same thread can't lock the same mutex twice */ + LOG_ERROR("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", + tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); + + _mutex_unlock(&_mutextree_mutex); + return; + } + } else if (tmutex->thread_id == th->thread_id) { + /* Mutex locked by this thread (not this mutex) */ + locks++; + } + + node = avl_get_next(node); + } + + if (locks > 0) { + /* Has already got a mutex locked */ + if (_multi_mutex.thread_id != th->thread_id) { + /* Tries to lock two mutexes, but has not got the double mutex, norty boy! */ + LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!", + _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); + } + } + + _mutex_unlock(&_mutextree_mutex); + } +# endif /* CHECK_MUTEXES */ + + _mutex_lock(mutex); + + _mutex_lock(&_mutextree_mutex); + + LOG_DEBUG("Locked %p by thread %d", mutex, th ? th->thread_id : -1); + mutex->line = line; + if (th) { + mutex->thread_id = th->thread_id; + } + + _mutex_unlock(&_mutextree_mutex); +#else + _mutex_lock(mutex); +#endif /* DEBUG_MUTEXES */ +} + +void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file) +{ +#ifdef DEBUG_MUTEXES + thread_t *th = thread_self(); + + if (!th) { + LOG_ERROR("No record for %u in unlock [%s:%d]", thread_self(), file, line); + } + + LOG_DEBUG("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); + + mutex->line = line; + +# ifdef CHECK_MUTEXES + if (th) { + int locks = 0; + avl_node *node; + mutex_t *tmutex; + + _mutex_lock(&_mutextree_mutex); + + while (node) { + tmutex = (mutex_t *)node->key; + + if (tmutex->mutex_id == mutex->mutex_id) { + if (tmutex->thread_id != th->thread_id) { + LOG_ERROR("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, + mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name); + _mutex_unlock(&_mutextree_mutex); + return; + } + } else if (tmutex->thread_id == th->thread_id) { + locks++; + } + + node = avl_get_next (node); + } + + if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) { + /* Don't have double mutex, has more than this mutex left */ + + LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!", + _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line); + } + + _mutex_unlock(&_mutextree_mutex); + } +# endif /* CHECK_MUTEXES */ + + _mutex_unlock(mutex); + + _mutex_lock(&_mutextree_mutex); + + LOG_DEBUG("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); + mutex->line = -1; + if (mutex->thread_id == th->thread_id) { + mutex->thread_id = MUTEX_STATE_NOTLOCKED; + } + + _mutex_unlock(&_mutextree_mutex); +#else + _mutex_unlock(mutex); +#endif /* DEBUG_MUTEXES */ +} + +void thread_cond_create_c(cond_t *cond, int line, char *file) +{ + pthread_cond_init(&cond->sys_cond, NULL); + pthread_mutex_init(&cond->cond_mutex, NULL); +} + +void thread_cond_destroy(cond_t *cond) +{ + pthread_mutex_destroy(&cond->cond_mutex); + pthread_cond_destroy(&cond->sys_cond); +} + +void thread_cond_signal_c(cond_t *cond, int line, char *file) +{ + pthread_cond_signal(&cond->sys_cond); +} + +void thread_cond_broadcast_c(cond_t *cond, int line, char *file) +{ + pthread_cond_broadcast(&cond->sys_cond); +} + +void thread_cond_wait_c(cond_t *cond, int line, char *file) +{ + pthread_mutex_lock(&cond->cond_mutex); + pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex); + pthread_mutex_unlock(&cond->cond_mutex); +} + +void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file) +{ + pthread_rwlock_init(&rwlock->sys_rwlock, NULL); +} + +void thread_rwlock_destroy(rwlock_t *rwlock) +{ + pthread_rwlock_destroy(&rwlock->sys_rwlock); +} + +void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file) +{ + pthread_rwlock_rdlock(&rwlock->sys_rwlock); +} + +void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file) +{ + pthread_rwlock_wrlock(&rwlock->sys_rwlock); +} + +void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file) +{ + pthread_rwlock_unlock(&rwlock->sys_rwlock); +} + +void thread_exit_c(int val, int line, char *file) +{ + thread_t *th = thread_self(); + +#if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES) + if (th) { + avl_node *node; + mutex_t *tmutex; + char name[40]; + + _mutex_lock(&_mutextree_mutex); + + while (node) { + tmutex = (mutex_t *)node->key; + + if (tmutex->thread_id == th->thread_id) { + LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]", + th->thread_id, th->name, file, line, mutex_to_string(tmutex, name)); + } + + node = avl_get_next (node); + } + + _mutex_unlock(&_mutextree_mutex); + } +#endif + + if (th) { + LOG_INFO("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); + + _mutex_lock(&_threadtree_mutex); + avl_delete(_threadtree, th, _free_thread); + _mutex_unlock(&_threadtree_mutex); + } + + pthread_exit((void *)val); +} + +/* sleep for a number of microseconds */ +void thread_sleep(unsigned long len) +{ +#ifdef _WIN32 + Sleep(len / 1000); +#else +# ifdef HAVE_NANOSLEEP + struct timespec time_sleep; + struct timespec time_remaining; + int ret; + + time_sleep.tv_sec = len / 1000000; + time_sleep.tv_nsec = len % 1000000; + + ret = nanosleep(&time_sleep, &time_remaining); + while (ret != 0 && errno == EINTR) { + time_sleep.tv_sec = time_remaining.tv_sec; + time_sleep.tv_nsec = time_remaining.tv_nsec; + + ret = nanosleep(&time_sleep, &time_remaining); + } +# else + struct timeval tv; + + tv.tv_sec = len / 1000000; + tv.tv_usec = (len % 1000000) / 1000; + + select(0, NULL, NULL, NULL, &tv); +# endif +#endif +} + +static void *_start_routine(void *arg) +{ + thread_start_t *start = (thread_start_t *)arg; + void *(*start_routine)(void *) = start->start_routine; + void *real_arg = start->arg; + thread_t *thread = start->thread; + + _block_signals(); + + free(start); + + /* insert thread into thread tree here */ + _mutex_lock(&_threadtree_mutex); + thread->sys_thread = pthread_self(); + avl_insert(_threadtree, (void *)thread); + _mutex_unlock(&_threadtree_mutex); + + LOG_INFO("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line); + + if (start->detached) { + pthread_detach(thread->sys_thread); + } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + /* call the real start_routine and start the thread + ** this should never exit! + */ + (start_routine)(real_arg); + + LOG_WARN("Thread x should never exit from here!!!"); + + return NULL; +} + +thread_t *thread_self(void) +{ + avl_node *node; + thread_t *th; + pthread_t sys_thread = pthread_self(); + + _mutex_lock(&_threadtree_mutex); + + if (_threadtree == NULL) { + LOG_WARN("Thread tree is empty, this must be wrong!"); + _mutex_unlock(&_threadtree_mutex); + return NULL; + } + + node = avl_get_first(_threadtree); + + while (node) { + th = (thread_t *)node->key; + + if (th && pthread_equal(sys_thread, th->sys_thread)) { + _mutex_unlock(&_threadtree_mutex); + return th; + } + + node = avl_get_next(node); + } + _mutex_unlock(&_threadtree_mutex); + + + LOG_ERROR("Nonexistant thread alive..."); + + return NULL; +} + +void thread_rename(const char *name) +{ + thread_t *th; + + th = thread_self(); + if (th->name) free(th->name); + + th->name = strdup(name); +} + +static void _mutex_lock(mutex_t *mutex) +{ + pthread_mutex_lock(&mutex->sys_mutex); +} + +static void _mutex_unlock(mutex_t *mutex) +{ + pthread_mutex_unlock(&mutex->sys_mutex); +} + + +void thread_library_lock(void) +{ + _mutex_lock(&_library_mutex); +} + +void thread_library_unlock(void) +{ + _mutex_unlock(&_library_mutex); +} + +void thread_join(long thread) +{ + void *ret; + int i; + + i = pthread_join(thread, &ret); +} + +/* AVL tree functions */ + +static int _compare_mutexes(void *compare_arg, void *a, void *b) +{ + mutex_t *m1, *m2; + + m1 = (mutex_t *)a; + m2 = (mutex_t *)b; + + if (m1->mutex_id > m2->mutex_id) + return 1; + if (m1->mutex_id < m2->mutex_id) + return -1; + return 0; +} + +static int _compare_threads(void *compare_arg, void *a, void *b) +{ + thread_t *t1, *t2; + + t1 = (thread_t *)a; + t2 = (thread_t *)b; + + if (t1->thread_id > t2->thread_id) + return 1; + if (t1->thread_id < t2->thread_id) + return -1; + return 0; +} + +static int _free_mutex(void *key) +{ + mutex_t *m; + + m = (mutex_t *)key; + + if (m && m->file) { + free(m->file); + m->file = NULL; + } + + /* all mutexes are static. don't need to free them */ + + return 1; +} + +static int _free_thread(void *key) +{ + thread_t *t; + + t = (thread_t *)key; + + if (t->file) + free(t->file); + if (t->name) + free(t->name); + + free(t); + + return 1; +} + + + + + + + + + + + + diff --git a/thread/thread.h b/thread/thread.h new file mode 100644 index 0000000..a352265 --- /dev/null +++ b/thread/thread.h @@ -0,0 +1,144 @@ +/* thread.h + * - Thread Abstraction Function Headers + * + * Copyright (c) 1999, 2000 the icecast team + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __THREAD_H__ +#define __THREAD_H__ + +#include + +typedef struct thread_tag { + /* the local id for the thread, and it's name */ + long thread_id; + char *name; + + /* the time the thread was created */ + time_t create_time; + + /* the file and line which created this thread */ + char *file; + int line; + + /* the system specific thread */ + pthread_t sys_thread; +} thread_t; + +typedef struct mutex_tag { + /* the local id and name of the mutex */ + long mutex_id; + char *name; + + /* the thread which is currently locking this mutex */ + long thread_id; + + /* the file and line where the mutex was locked */ + char *file; + int line; + + /* the system specific mutex */ + pthread_mutex_t sys_mutex; +} mutex_t; + +typedef struct cond_tag { + long cond_id; + char *name; + + pthread_mutex_t cond_mutex; + pthread_cond_t sys_cond; +} cond_t; + +typedef struct rwlock_tag { + long rwlock_id; + char *name; + + /* information on which thread and where in the code + ** this rwlock was write locked + */ + long thread_id; + char *file; + int line; + + pthread_rwlock_t sys_rwlock; +} rwlock_t; + +#define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__) +#define thread_mutex_create(x) thread_mutex_create_c(x,__LINE__,__FILE__) +#define thread_mutex_lock(x) thread_mutex_lock_c(x,__LINE__,__FILE__) +#define thread_mutex_unlock(x) thread_mutex_unlock_c(x,__LINE__,__FILE__) +#define thread_cond_create(x) thread_cond_create_c(x,__LINE__,__FILE__) +#define thread_cond_signal(x) thread_cond_signal_c(x,__LINE__,__FILE__) +#define thread_cond_broadcast(x) thread_cond_broadcast_c(x,__LINE__,__FILE__) +#define thread_cond_wait(x) thread_cond_wait_c(x,__LINE__,__FILE__) +#define thread_rwlock_create(x) thread_rwlock_create_c(x,__LINE__,__FILE__) +#define thread_rwlock_rlock(x) thread_rwlock_rlock_c(x,__LINE__,__FILE__) +#define thread_rwlock_wlock(x) thread_rwlock_wlock_c(x,__LINE__,__FILE__) +#define thread_rwlock_unlock(x) thread_rwlock_unlock_c(x,__LINE__,__FILE__) +#define thread_exit(x) thread_exit_c(x,__LINE__,__FILE__) + +#define MUTEX_STATE_NOTLOCKED -1 +#define MUTEX_STATE_NEVERLOCKED -2 +#define MUTEX_STATE_UNINIT -3 +#define THREAD_DETACHED 1 +#define THREAD_ATTACHED 0 + +/* init/shutdown of the library */ +void thread_initialize(void); +void thread_initialize_with_log_id(int log_id); +void thread_shutdown(void); + +/* creation, destruction, locking, unlocking, signalling and waiting */ +long thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file); +void thread_mutex_create_c(mutex_t *mutex, int line, char *file); +void thread_mutex_lock_c(mutex_t *mutex, int line, char *file); +void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file); +void thread_mutex_destroy(mutex_t *mutex); +void thread_cond_create_c(cond_t *cond, int line, char *file); +void thread_cond_signal_c(cond_t *cond, int line, char *file); +void thread_cond_broadcast_c(cond_t *cond, int line, char *file); +void thread_cond_wait_c(cond_t *cond, int line, char *file); +void thread_cond_destroy(cond_t *cond); +void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file); +void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file); +void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file); +void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file); +void thread_rwlock_destroy(rwlock_t *rwlock); +void thread_exit_c(int val, int line, char *file); + +/* sleeping */ +void thread_sleep(unsigned long len); + +/* for using library functions which aren't threadsafe */ +void thread_library_lock(void); +void thread_library_unlock(void); +#define PROTECT_CODE(code) { thread_library_lock(); code; thread_library_unlock(); } + +/* thread information functions */ +thread_t *thread_self(void); + +/* renames current thread */ +void thread_rename(const char *name); + +/* waits until thread_exit is called for another thread */ +void thread_join(long thread); + +#endif /* __THREAD_H__ */ + + + diff --git a/timing/BUILDING b/timing/BUILDING new file mode 100644 index 0000000..0aa7006 --- /dev/null +++ b/timing/BUILDING @@ -0,0 +1,7 @@ +defines that affect compilation + +none + +library dependencies + +none diff --git a/timing/COPYING b/timing/COPYING new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/timing/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/timing/Makefile.am b/timing/Makefile.am new file mode 100644 index 0000000..7a2be94 --- /dev/null +++ b/timing/Makefile.am @@ -0,0 +1,18 @@ +## Process this with automake to create Makefile.in + +AUTOMAKE_OPTIONS = foreign + +noinst_LTLIBRARIES = libicetiming.la +noinst_HEADERS = timing.h + +libicetiming_la_SOURCES = timing.c + +# SCCS stuff (for BitKeeper) +GET = true + +debug: + $(MAKE) all CFLAGS="@DEBUG@" + +profile: + $(MAKE) all CFLAGS="@PROFILE@" + diff --git a/timing/README b/timing/README new file mode 100644 index 0000000..b43ead9 --- /dev/null +++ b/timing/README @@ -0,0 +1,5 @@ +this is the timing library. + +lgpl + +by jack moffitt diff --git a/timing/TODO b/timing/TODO new file mode 100644 index 0000000..585db89 --- /dev/null +++ b/timing/TODO @@ -0,0 +1,2 @@ + +nothing diff --git a/timing/timing.c b/timing/timing.c new file mode 100644 index 0000000..a6c0940 --- /dev/null +++ b/timing/timing.c @@ -0,0 +1,40 @@ +/* timing.c +** - Timing functions +*/ + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include "timing.h" + +/* + * Returns milliseconds no matter what. + */ +long long timing_get_time(void) +{ +#ifdef _WIN32 + return timeGetTime(); +#else + struct timeval mtv; + + gettimeofday(&mtv, NULL); + + return (long long)(mtv.tv_sec) * 1000 + (long long)(mtv.tv_usec) / 1000; +#endif +} + +void timing_sleep(long long sleeptime) +{ + struct timeval sleeper; + + sleeper.tv_sec = 0; + sleeper.tv_usec = sleeptime * 1000; + + select(0, NULL, NULL, NULL, &sleeper); +} diff --git a/timing/timing.h b/timing/timing.h new file mode 100644 index 0000000..42b3110 --- /dev/null +++ b/timing/timing.h @@ -0,0 +1,7 @@ +#ifndef __TIMING_H__ +#define __TIMING_H__ + +long long timing_get_time(void); +void timing_sleep(long long sleeptime); + +#endif /* __TIMING_H__ */